0

I have a UIImageView displaing an image. This view's layer is masked with CAShapeLayer in order to create circular "hole" in the image. To create the hole I use UIBezierPath with .usesEvenOddFillRule = true.

It works fine when static. But I need that hole to move with user finger. To do that I create new UIBezierPath with even-odd rule each time user moves their finger. On smaller phones with smaller images it looks OK but on iPhone 6 Plus it is choppy.

Any ideas on how to make it smooth are very wellcome. I cannot just move the frame of masking CAShapeLayer - it would move the hole bot also hide some edges of the image. So the only way is to change its .path each time user moves finger and that is slow.


EDIT: matt's answer would work in some scenarios but not in my case: I am not displaying the whole image only a part of it defined by UIBezierPath. This part is most often oval (but can be rectangular or rounded rectangle) and it has "hole" cut in it. While the hole is mowing with users finger the displayed part/shape of the image does not change - it is static.

The ineficient solution that was in place so far wa:

  1. Create UIBezierPath with boundary of displayed part of the image
  2. Set 'even off fill rule' on it
  3. Add UIBezierPath of the hole to it
  4. Set it as path of CAShapeLayer with some opaque fill color
  5. Use that CAShapeLayer as mask of the UIImageView

This procedure was repeated each time a user moved their finger. I cannot simply move the whole mask layer as that would also change the part of the image being displayed. I what it to stay static and move only the hole in it.

Community
  • 1
  • 1
Rasto
  • 17,204
  • 47
  • 154
  • 245

1 Answers1

1

it would move the hole bot also hide some edges of the image

Well, I don't agree. Moving the mask is exactly the way to do this. I don't see why you think there's a problem with that. Perhaps the issue is merely that you have not made the mask layer big enough. It does not have to be the same size as the layer it is masking. In this case, it needs to be about 9 times the size of the masked layer (3 horizontal and 3 vertical), so that it will continue to cover the masked the layer no matter how far in any direction the user slides it.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 1
    Mask the image view and also mask its super view. – matt Mar 03 '16 at 20:31
  • Yes, that should work! Little too much work my view heirarchy and lots of other factors I did not mention here to keep it simple... But if I cannot think of any other way I will have no choice but do that work. Thank you. – Rasto Mar 03 '16 at 20:33
  • Sure. In your other question, you asked how to mask one layer twice. But you didn't explain what you are really trying to do. A superlayer mask masks a sublayer. So mask _two_ layers, one a subview of the other. Just create a superview for the image view, the same size as the image view, for no other purpose than so you can mask it. I do that sort of thing all the time. – matt Mar 03 '16 at 20:38