Search code examples
objective-ccocoacore-animationcgpath

Animating a CGMutablePathRef with CAShapeLayer


I'm trying to animate a path and with the changing of it's points, as shown in the keyframes below. So, the top two points move down to the bottom and the middle point moves to the top, essentially flipping it's direction.

Keyframes

Here's the code I'm using to create the path:

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 1.0f, 8.0f);
CGPathAddLineToPoint(path, nil, 7.0f, 1.5f);
CGPathAddLineToPoint(path, nil, 13.0f, 8.0f);

shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.path = path;
shapeLayer.strokeColor = pathColor.CGColor;
shapeLayer.fillColor = [NSColor clearColor].CGColor;
shapeLayer.lineWidth = 2.0f;
[self.layer addSublayer: shapeLayer];

However, I've also got little idea of how to actually animate the points. All the information about animating paths online is simply changing the path start, not the actual point.

Is there a way - or a different approach - to do this? Thanks in advance.


Solution

  • You can animate the path of the shape layer from one path to another.

    In your case you would create the paths for the initial state and for the end state as two different paths.

    Note: if your two paths have a different number of segments or control points, the animation will look very strange.

    Then you would create an animation for the "path" key path with those to and from values and add it to the layer you are animating. If you also want the property to change to the end state you should also update the path property to reflect the end state of the animation.

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
    animation.duration  = 1.0; // however long your duration should be
    animation.fromValue = (__bridge id)fromPath;
    animation.toValue   = (__bridge id)toPath;
    
    shapeLayer.path = toPath; // the property should reflect the end state of the animation
    [shapeLayer addAnimation:animation forKey:@"myPathAnimation"];