I have an UIImageView and another view overlapping it which allows me to draw in it. When I draw something, it has the correct dimensions and placement, but when I try to apply that as a mask on the image view, it has a weird y offset, as shown on Image 1 captured from view hierarchy.
I am applying the mask like this:
canvas.onTouchesEnd = { [weak self] in
guard let self = self else { return }
self.backgroundView.layer.mask = self.canvas.layer
}
canvas is the view where I draw shapes (red one on the image), and backgroundView is the image view I'm trying to mask. "onTouchesEnd" is just a callback which is called upon finishing drawing the shape.
UIImageView is created in storyboard and constraints are set there.
I've tried setting translatesAutoresizingMaskIntoConstraints = false, returning the path from canvas and creating a new layer for mask, but whatever I do, it has the same offset and nothing really worked.
Any ideas how to correctly translate this path from canvas onto image view mask?
The reason your mask has a "weird y offset" is because of the way you are accessing the other view's layer.
With your code, the
canvas.layerwill come with an origin relative to its superview - in this case, the "root" view of the controller.If you put your image view and "canvas" at the top (of the view, not top of the safe area), it should line up.
However, that's really not an ideal way to do this - and
self.backgroundView.layer.mask = self.canvas.layeris not a good idea to begin with.You didn't show us what you're doing with your "canvas" view, but assuming it has a
CAShapeLayerwhere you set the path (and line width, line join, etc), you could use this as your closure:What you might want to consider, though, is a using a subclassed
UIImageViewthat would handle the touches and masking itself... avoiding all of that.Here's a quick "scratch off" example:
This is now completely self-contained. If you add a
UIImageViewin Storyboard, set its Custom Class toScratchOffImageview(and enable User Interaction), you're all done.You can test it with this sample view controller - requires an image asset named "sampleImage" (or edit the code with your image name):
You'll notice in the comments that the custom "scratch off" image view will start completely clear / transparent -- and you won't see anything and won't know where to touch/drag... so I inserted a bordered "frame" view below it.
Looks like this: