I'd like to animate a mask I placed on a UIImageView
using the contents property of the CALayer
. Unfortunately my current implementation
only seems to animate between the first and last images of the array without passing between the transitions. Is there any way of achieving this, or should I be looking at other things like CAReplicatorLayer
?
Here's what I currently have:
let mask = CALayer()
mask.frame = self.frame
self.layer.mask = mask
mask.contents = transitions.first?.cgImage
let maskAnimation = CABasicAnimation(keyPath: "contents")
maskAnimation.fromValue = transitions.first?.cgImage
maskAnimation.toValue = transitions.last?.cgImage
maskAnimation.duration = duration
mask.contents = transitions.last
mask.add(maskAnimation, forKey: "ContentsAnimation")
The animation system doesn't magically know what it means to interpolate between the first and last images; you have to tell it, explicitly. That is exactly what a keyframe animation is for.
Here's an example of forming such an animation, from a project of mine:
let anim = CAKeyframeAnimation(keyPath:#keyPath(CALayer.contents))
anim.values = self.images.map {$0.cgImage!}
anim.keyTimes = [0.0, 0.25, 0.5, 0.75, 1.0]
anim.calculationMode = kCAAnimationDiscrete
anim.duration = 1.5
As you can see, we have an array of images; they are UIImages, so I have to derive their CGImage backing (I assume your transitions
is similar). The keyTimes
array is used to divide up the duration
into frames; I'm doing this division a little oddly because of the nature of my animation, so feel free to fix the times to divide the duration evenly.