Smootly mooving a hole in UIImage?

2019-09-09 12:23发布

问题:

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.

回答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.