iosswiftuiscrollviewuikitcrop

Crop the current touch point on a UIScrollView and display it in a UIView


I'm working on a drawing feature. I need the user to be able to see what is being drawn under their finger. The photo is inside of a UIScrollView. I basically just want to crop the area around the current pointer location and display it in a separate view at the top of the screen. The following GIF is from Android and shows the behavior I want to implement (see the circular region at the top, which I call the "zoomer" window):

Here's the effect I want to achieve

I'm having trouble implementing this in iOS. The following code is my attempt to implement this zoomer window as a rectangle:

UIGraphicsBeginImageContextWithOptions(CGSize(width: zoomerWindowWidth, height: zoomerWindowWidth), false, 0)
let cropRect = CGRect(
        x: -(lastPointTouched.x - zoomerWindowWidth / 2),
        y: -(lastPointTouched.y + zoomerWindowWidth / 2),
        width: view.bounds.size.width,
        height: view.bounds.size.height
)

mainScrollView.drawHierarchy(in: cropRect, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
zoomerImageView.image = image

This almost works, but the current touch point doesn't stay centered in the zoomer window. And when the UIScrollView is zoomed in or out, the window gets even more out of alignment. My attempts to multiply by a scale factor have all failed.

Here's what it currently looks like:

What it currently looks like

TLDR: I need the little window to stay centered on the current touch location. Can anyone help?

Here's the full codebase: https://github.com/gavingt/ios_draw_zoom . See here in particular.


Solution

  • A friendly Redditor found the solution:

    let lastPointTouched = view.convert(self.lastPointTouched, from: drawingImageView)
    let cropRect = CGRect(
            x: -(lastPointTouched.x - zoomerWindowWidth / 2),
            y: -(lastPointTouched.y - zoomerWindowWidth/2 ),
            width: view.bounds.size.width,
            height: view.bounds.size.height
    )
    

    You can also check the latest Github commit for the working version.