I have a view with .brown
backgroundColor
.
In that view I have a backgroundView
, which has backgroundColor: UIColor.black.withAlphaComponent(0.5)
.
I then want to have a transparent box in this backgroundView
which shows the underlaying view. And I have achieved that, but I can't do it by animating its transparency, my code only grows the "cut out area" until desired size instead of animating it's transparency.
Brown view with the backgroundView and it's 0.5 alpha
Added layer to backgroundView shows part of the brown view
The code I've written to get what I have now is this:
func addIndicatorTo(global frame: CGRect) {
let shape = CAShapeLayer()
let targetRect = convert(frame, from: nil).insetBy(dx: -4, dy: -4)
let animation = CABasicAnimation(keyPath: "path")
let toPath = CGMutablePath()
toPath.addRect(bounds)
toPath.addPath(UIBezierPath(roundedRect: targetRect,
byRoundingCorners: .allCorners,
cornerRadii: CGSize(width: 4, height: 4)).cgPath)
toPath.closeSubpath()
let fromPath = CGMutablePath()
fromPath.addRect(bounds)
fromPath.addPath(UIBezierPath(roundedRect: targetRect.insetBy(dx: targetRect.width / 2,
dy: targetRect.height / 2),
byRoundingCorners: .allCorners,
cornerRadii: CGSize(width: 4, height: 4)).cgPath)
fromPath.closeSubpath()
animation.fromValue = fromPath
animation.toValue = toPath
animation.duration = 0.5
shape.fillRule = .evenOdd
shape.path = animation.fromValue as! CGPath
backgroundView.layer.mask = shape
shape.add(animation, forKey: nil)
CATransaction.begin()
CATransaction.setDisableActions(true)
shape.path = toPath
CATransaction.commit()
}
Not sure if this is a "good" solution. But I will go with this until someone tells shows me how to solve it more elegantly!
Basically I just create a mask with the box cut out, then I create a new boxLayer
with draws in the area of the "cutout". Then I just animate the opacity
of the boxLayer
.
func addIndicatorTo(global frame: CGRect) {
let maskLayer = CAShapeLayer()
let boxLayer = CAShapeLayer()
let targetRect = convert(frame, from: nil).insetBy(dx: -4, dy: -4)
let animation = CABasicAnimation(keyPath: "opacity")
let toPath = CGMutablePath()
let boxPath = UIBezierPath(roundedRect: targetRect,
byRoundingCorners: .allCorners,
cornerRadii: CGSize(width: 4, height: 4)).cgPath
toPath.addRect(bounds)
toPath.addPath(boxPath)
toPath.closeSubpath()
boxLayer.fillColor = UIColor.black.withAlphaComponent(0.5).cgColor
boxLayer.path = boxPath
animation.fromValue = 1.0
animation.toValue = 0.0
animation.duration = 0.5
maskLayer.fillRule = .evenOdd
maskLayer.path = toPath
backgroundView.layer.mask = maskLayer
layer.addSublayer(boxLayer)
boxLayer.add(animation, forKey: nil)
CATransaction.begin()
CATransaction.setDisableActions(true)
boxLayer.opacity = 0.0
CATransaction.commit()
}