I have a UIView whose layer has 2 sublayers, one is a CAShapeLayer, and the other a CALayer.
The CAShapeLayer has a path set using bezierPathWithOvalInRect, and is animated using CABasicAnimation. The "strokeEnd" property is animated from 0.0 to 1.0, over a certain duration. This has the effect of seeing the oval draw from beginning to end over the duration.
The CALayer simply has its contents set to a pencil image, and is animated using CAKeyframeAnimation. The "position" property is animated by setting the path property of the CAKeyframeAnimation to the same path as the CAShapeLayer, and the same duration as the CABasicAnimation. This has the effect of the pencil moving along the same path during the same duration, and it looks like the pencil is drawing the oval.
Works beautifully in iOS6. However, in iOS7, the timing is off - the position and strokeEnd animations are not in sync - they are in sync at specific moments, specifically at times 0, duration/4, duration/2, duration*3/4, and duration - but in between, the synchronization is off.
If instead of an ellipse, I use a rectangle or triangle, for example, it works great in iOS6 and iOS7. Only issue is an ellipse in iOS7.
Essentially I need to know how to synchronize 2 different animations, where each animation is animating a different layer.
Here is the code that creates the 2 layers:
self.drawingLayer = [CAShapeLayer layer];
self.drawingLayer.frame = self.view.bounds;
self.drawingLayer.bounds = drawingRect;
self.drawingLayer.path = path.CGPath;
self.drawingLayer.strokeColor = [[UIColor blackColor] CGColor];
self.drawingLayer.fillColor = nil;
self.drawingLayer.lineWidth = 10.0f;
self.drawingLayer.lineJoin = kCALineJoinRound;
self.drawingLayer.lineCap = kCALineJoinRound;
[self.view.layer addSublayer:self.drawingLayer];
UIImage *pencilImage = [UIImage imageNamed:@"pencil.png"];
self.pencilLayer = [CALayer layer];
self.pencilLayer.contents = (id)pencilImage.CGImage;
self.pencilLayer.contentsScale = [UIScreen mainScreen].scale;
self.pencilLayer.anchorPoint = CGPointMake(0.0, 1.0); //bottom left corner
self.pencilLayer.frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
[self.view.layer addSublayer:self.pencilLayer];
And here is the code that creates and starts the 2 different animations (self.drawingLayer is the CAShapeLayer, and self.pencilLayer is the CALayer)
CABasicAnimation *drawingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawingAnimation.duration = 10.0;
drawingAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawingAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[self.drawingLayer addAnimation:drawingAnimation forKey:@"strokeEnd"];
CAKeyframeAnimation *pencilAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pencilAnimation.duration = drawingAnimation.duration;
pencilAnimation.path = self.drawingLayer.path;
pencilAnimation.calculationMode = kCAAnimationPaced;
pencilAnimation.delegate = self;
pencilAnimation.fillMode = kCAFillModeForwards;
pencilAnimation.removedOnCompletion = NO;
[self.pencilLayer addAnimation:pencilAnimation forKey:@"position"];
UPDATE
Here's a test app that illustrates the problem.
CATransaction
? Right now each one is taking place in its own implicit transaction preventing synchronization. developer.apple.com/library/ios/documentation/GraphicsImaging/… – Brian Nickel♦