I am trying to get erase functionality working with CAShapeLayer. Current code:
class MaskTestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let image = UIImage(named: "test.jpg")!
let testLayer = CAShapeLayer()
testLayer.contents = image.cgImage
testLayer.frame = view.bounds
let maskLayer = CAShapeLayer()
maskLayer.opacity = 1.0
maskLayer.lineWidth = 20.0
maskLayer.strokeColor = UIColor.black.cgColor
maskLayer.fillColor = UIColor.clear.cgColor
maskLayer.frame = view.bounds
testLayer.mask = maskLayer
view.layer.addSublayer(testLayer)
}
}
I was thinking if I create a mask layer then I could draw a path on the mask layer and erase parts of the image eg:
let path = UIBezierPath()
path.move(to: CGPoint(x: 100.0, y: 100.0))
path.addLine(to: CGPoint(x: 200.0, y: 200.0))
maskLayer.path = path.cgPath
However it seems that when I add the maskLayer
it covers the entire image and I can’t see the contents below it. What am I doing wrong here?
2
Answers
maskLayer has no initial path therefore its content is not filled, also filling it with .clear will completely mask the image.
This works for me:
Not actually sure if a combination of stroke and fill works but maybe someone else comes up with a solution. If you want to cut out shapes from your path you could try something like this:
You can use a bezier path mask to "erase" the path by creating a custom
CALayer
subclass and overridingdraw(in ctx: CGContext)
:Here’s a complete example… we’ll create a
UIView
subclass and, since the effect will be "scratching off the image" we’ll call itScratchOffImageView
:and, an example view controller:
It will look like this to start – I used a 3:2 image, and overlaid it on a light-gray label with red text so we can see that we are "scratching off" the image:
then, after a little bit of "scratching":
and after a lot of "scratching":