Asana / Drawsana

An open source library that lets your users draw on things - mark up images with text, shapes, etc.
https://asana.github.io/Drawsana/
MIT License
649 stars 102 forks source link

Add resize/rotate to Selection tool #20

Open rogermolas opened 5 years ago

rogermolas commented 5 years ago

Hi, Im looking for a solution how to resize or rotate shape after its drawn, the behaviour is only available in TextTool. How to do the same thing in other shapes?

Thanks, Roger

rogermolas commented 5 years ago

Temporary Solution: During Selection tool state, i disable the drawing view touches and added UIPinchGestureRecognizer to image view to handle the pinch. keep the reference of drawingView.toolSettings.selectedShape as the current shape

if gesture.state == .began ||  gesture.state == .changed  {
   let currentScale = shape.transform.scale

   let maxScale: CGFloat  = 2.0
   let minScale: CGFloat  = 1.0
   var newScale: CGFloat = 1 - (lastScale - gesture.scale)

   newScale = min(newScale, maxScale / currentScale)
   newScale = max(newScale, minScale / currentScale)
   let transform = shape.transform.scaled(by: newScale)
   lastScale = gesture.scale

   drawingView.toolSettings.isPersistentBufferDirty = true
   let operation = ScaleOperation(shape: shape,
                            transform: transform,
                           originalTransform: originalTransform)
   drawingView.operationStack.apply(operation: operation)
}
struct ScaleOperation: DrawingOperation {
    let shape: ShapeWithTransform
    let transform: ShapeTransform
    let originalTransform: ShapeTransform

    func shouldAdd(to operationStack: DrawingOperationStack) -> Bool {
        return true
    }

   func apply(drawing: Drawing) {
        shape.transform = transform
        drawing.update(shape: shape)
    }

    func revert(drawing: Drawing) {
        shape.transform = originalTransform
        drawing.update(shape: shape)
    }
}

It works fine, but maybe you have other solutions i can consider?

Thanks, Roger

rashidabbas commented 5 years ago

@rogermolas good work, can you please help me to improve eraser tool with selection tool. when I erase some drawing and then select drawing that was erased some piece of drawing but when I move select tool it move complete drawing that was erased earlier.

it means that eraser does not erase from canvas it just paint on drawing with background colour.

please help me how can I erase drawing from canvas. Thanks in advance.

stevelandeyasana commented 5 years ago

The eraser does actually erase from the canvas. It does not paint in a background color. Our primary use case is drawing on top of images.

A correct permanent solution would be to improve the tool API to handle multiple touches and add this behavior to the selection tool.

carlosrc commented 3 years ago

@rogermolas hello. Is your solution still valid? I tried it, but I couldn't make it work right.

Any help? Thanks!

rogermolas commented 3 years ago
@IBAction func resizeAction(sender: UIButton) {
        guard drawingView.toolSettings.selectedShape != nil else {
            let alert = UIAlertController(title: "No Selected Shape",
                                          message: "Please use selection toool and select shape you wish to resize",
                                          preferredStyle: .alert)
            let ok = UIAlertAction(title: "Ok", style: .default, handler: nil)
            alert.addAction(ok)
            present(alert, animated: true, completion: nil)
            return
        }

        self.shape = drawingView.toolSettings.selectedShape
        self.originalTransform = shape.transform
        self.startPoint = shape.transform.translation

        if isResizing {
            if  drawingView.toolSettings.selectedShape == nil  {
                 return
            }
            self.imageView.gestureRecognizers?.removeAll()
            self.imageView.isUserInteractionEnabled = true
            self.drawingView.isMultipleTouchEnabled = true
            self.drawingView.isUserInteractionEnabled = true
            isResizing = false
        } else {
            let pinch = UIPinchGestureRecognizer(target: self, action: #selector(pinch(gesture:)))
            self.imageView.addGestureRecognizer(pinch)
            self.imageView.isUserInteractionEnabled = true
            self.imageView.isMultipleTouchEnabled = true
            self.drawingView.isUserInteractionEnabled = false
            self.resizeButton.setTitle("Done", for: .normal)
            isResizing = true
        }
    }

**Add gesture

@objc func pinch(gesture: UIPinchGestureRecognizer) {
        guard drawingView.toolSettings.selectedShape != nil else {
            return
        }

        if gesture.state == .began {
            lastScale = gesture.scale
        }

        if gesture.state == .began ||  gesture.state == .changed {
            let currentScale = shape.transform.scale
            // Constants to adjust the max/min values of zoom
            let kMaxScale: CGFloat  = 2.0
            let kMinScale: CGFloat  = 0.5
            var newScale: CGFloat = 1 - (lastScale - gesture.scale)

            newScale = min(newScale, kMaxScale / currentScale)
            newScale = max(newScale, kMinScale / currentScale)
            let transform = shape.transform.scaled(by: newScale)
            lastScale = gesture.scale

            drawingView.toolSettings.isPersistentBufferDirty = true
            let operation = ScaleOperation(shape: drawingView.toolSettings.selectedShape!,
                                           transform: transform,
                                           originalTransform: originalTransform)
            drawingView.operationStack.apply(operation: operation)
        }
    }
carlosrc commented 3 years ago

Thanks for your answer @rogermolas ! But still can't make it work right...

When I pinch, the selection area goes fine, but the draw doesn't get its proper position. I attach a few images:

Screen Shot 2021-02-15 at 17 28 55 Screen Shot 2021-02-15 at 17 29 10 Screen Shot 2021-02-15 at 17 29 54