Implicit Animation for CAShapeLayer's Path
I was recently working on a project that required some custom drawing that also needed to be animated while resizing. I started out using Core Graphics in -drawRect
of my custom view but when it came around to animating the drawing it was not possible.
I decided to try out using a CAShapeLayer that allows you to set a path, line color, fill color and more. This worked beautifully for drawing but caused headaches at first as examples online all manually animated the path property of CAShapeLayer with a CABasicAnimation. My problem was that the view in question was within a table view cell and I was not explicitly resizing it so I couldn't find an elegant way to add my custom animation.
Then I found a method on CALayer called -actionForKey. This is called each time a property is changed to determine what action should be taken. You can return an animation for whatever property you desire. In my case I wanted to implicitly animate the path property so I implemented my own subclass of CAShapeLayer and implemented -actionForKey in the following way:
- (id<CAAction>)actionForKey:(NSString *)event {
if ([event isEqualToString:@"path"]) {
CABasicAnimation *animation = [CABasicAnimation
animationWithKeyPath:event
];
animation.duration = [CATransaction animationDuration];
animation.timingFunction = [CATransaction animationTimingFunction];
return animation;
}
return [super actionForKey:event];
}
Basically this method creates a basic animation which automatically uses the before and after value. The only things I have to set are the duration and timingFunction. I use the defaults in CATransaction so that I can override them from an external class if necessary with +setAnimationDuration: and +setAnimationTimingFunction:.
Now any time the path is changed on the layer it will automatically animate it. I can reset the path in my -layoutSubviews
and not worry about the rest.