Drawing on a UIImageView inside a UIScrollView
Asked Answered
A

2

13

I have a UIImageView inside a UIScrollView which automatically zooms out to fit the image supplied. The user can zoom as usual with a pinch gesture, and the pan gesture is set to require two touches since the drawing takes precedence.

On launch, everything looks great, but when I invoke my drawing code, this happens: enter image description here

As you can see, when drawLineFrom(fromPoint:toPoint:) is invoked, the UIImageView shrinks. After that, the drawing appears to work as intended (though it skips the first part of the line on every touch).

My UIPanGestureRecognizer selector:

@objc func onOneFingerDrawing(_ sender: UIPanGestureRecognizer) {
    switch sender.state {
    case .began:
        swiped = false

        lastPoint = sender.location(in: drawView.imageView)
    case .changed:
        swiped = true

        let currentPoint = sender.location(in: drawView.imageView)
        drawLineFrom(fromPoint: lastPoint, toPoint: currentPoint)

        lastPoint = currentPoint
    case .ended:
        guard drawView.scrollView.frame.contains(sender.location(in: drawView.imageView)) else {
            return
        }

        if let newImage = drawView.imageView.image {
            if history.count > historyIndex + 1 {
                history.removeLast((history.count - 1) - historyIndex)
            }

            history.append(newImage)
            historyIndex = history.count - 1
        }
    case .possible,
         .cancelled,
         .failed:
        return
    }
}

and my drawLineFrom(fromPoint:toPoint:):

@objc func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
    UIGraphicsBeginImageContextWithOptions(drawView.imageView.frame.size, false, UIScreen.main.scale)
    let context = UIGraphicsGetCurrentContext()
    context?.interpolationQuality = .none

    drawView.imageView.image?.draw(in: CGRect(x: 0, y: 0, width: drawView.imageView.frame.size.width, height: drawView.imageView.frame.size.height))

    context?.move(to: fromPoint)
    context?.addLine(to: toPoint)

    context?.setLineCap(.round)
    context?.setLineWidth(lineWidth)
    context?.setStrokeColor(lineColor)
    context?.setBlendMode(blendMode)

    context?.strokePath()

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    drawView.imageView.image = newImage
}
Anyhow answered 4/4, 2018 at 8:49 Comment(2)
You are creating image every time on drag since your drawLineFrom called on every time on gesture changed and you change image every timeSkirting
Did you ever figure this out? I am having a very similar problem. My drawing will draw in the area that is zoomed, but when I lift my finger, the drawing moves to the top left corner.Mongrelize
E
4

There is issue with image constraint with scrollview. Whenever you start rendering the image then its frame is changing according to content. So, you need to add aspect ratio constraint (as i did) or any size constraint to image view. see gifs for reference.

Before add image view size constraint.

enter image description here

After adding image view size constraint.

enter image description here

Encratia answered 4/6, 2018 at 7:1 Comment(2)
It's not a ratio problem. As you can see in my gif, the image ratio stays the same, but the zoom scale is acting up - I thinkAnyhow
all i mean to say, add proper size constraint for your imageview inside scrollview.Encratia
D
0

The drawing skips the first part of the line because you are using a UIPanGestureRecognizer. They system first determines it is a pan before it sends you a .began event. You should swap it to a generic UIGestureRecognizer to have it started immediately. You'll want to add in additional logic in that case checking for movement and number of fingers.

As far as the resizing, its tough to say without more info. I'd color the background of the ImageView as well. The first question is, is it the whole imageView that is shrinking or is it just the actual image inside it.

Dwinnell answered 31/5, 2018 at 22:35 Comment(1)
It is, but because it's the entire imageView that is being resized, it doesn't show.Anyhow

© 2022 - 2024 — McMap. All rights reserved.