Question

EDIT: Attached code for CAAnimationGroup, the animations draw sequentially, but I'm still getting the problem that firstAnimation disappears once secondAnimation starts and I've noticed in the documentation for CAAnimationGroup it says:

removedOnCompletion properties of animations in the animations property are currently ignored.

How do I get around this?


I'm trying to animate multiple CAKeyFrameAnimation objects on the same layer so that when firstAnimation finishes, the path it draws remains on the screen when secondAnimation gets kicked off so the end result is a picture made from the paths of both objects together on the screen.

Currently, if I put both animation objects (in order) in the same method and call that, only secondAnimation is drawn on the screen. If I split them up and call them sequentially, firstAnimation gets drawn to the screen, and then disappears when secondAnimation starts. By themselves, the animations work exactly as intended.

I've tried looking around for CAAnimationGroup examples because it seems to be what I'm looking for, but from the couple examples I've seen, it's not really obvious to me what's going on, or how to produce the effect I'm looking for, could anyone show me how to draw both animations sequentially and retain the results on the screen?

Here is my layer, my two animations, and my group:

CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.animationLayer.bounds;
pathLayer.bounds = pathRect;
pathLayer.geometryFlipped = YES;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = 10.0f;
pathLayer.lineJoin = kCALineJoinBevel;


CAKeyframeAnimation *firstAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
firstAnimation.beginTime = 0.0;
firstAnimation.duration = 4.0;
firstAnimation.removedOnCompletion = NO;   //Is being ignored by CAAnimationGroup
firstAnimation.fillMode = kCAFillModeForwards;
firstAnimation.values = [NSArray arrayWithObjects:
                         (id)path0.CGPath,(id)path1.CGPath,
                         (id)path2.CGPath,(id)path3.CGPath,
                         (id)path4.CGPath,(id)path5.CGPath,nil];
firstAnimation.keyTimes = [NSArray arrayWithObjects: 
                         [NSNumber numberWithFloat:0.0],
                         [NSNumber numberWithFloat:0.2],
                         [NSNumber numberWithFloat:0.21],
                         [NSNumber numberWithFloat:0.22],
                         [NSNumber numberWithFloat:0.63],
                         [NSNumber numberWithFloat:1.0], nil];



CAKeyframeAnimation *secondAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
secondAnimation.beginTime = 4.0; //This should come directly after firstAnimation
secondAnimation.duration = 3.0;
secondAnimation.removedOnCompletion = NO;   //Is being ignored by CAAnimationGroup
secondAnimation.fillMode = kCAFillModeForwards;
secondAnimation.values = [NSArray arrayWithObjects:
                          (id)path00.CGPath,(id)path01.CGPath,
                          (id)path02.CGPath,nil];
secondAnimation.keyTimes = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0],
                          [NSNumber numberWithFloat:0.8],
                          [NSNumber numberWithFloat:1.0],nil];



CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:firstAnimation,secondAnimation,nil];
group.duration = 7.0;  //The total time of the animations, don't know if redundant
group.delegate = self;

[self.pathLayer addAnimation:group forKey:@"path"];
Was it helpful?

Solution

Ok, so I've found a tentative hack to solve my problem, Till's comment worked great for pure serialization but the animations kept on disappearing so that does not work for my case at all.

The hack that I used was to create a separate layer for each animation instead of putting both animations on a single CAShapeLayer instance, and then specify the duration and keyTime for both animations according to a time controller so as to get 1) the sequence of times to be correct between animations and 2) the timing within each animation to be correct.

By using separate layers, removedOnComplete = NO works again since I'm not using CAAnimationGroup so my animations are persistent which is something I really need in my app.

I'm not going to immediately accept this answer though because this seems like a low-ball way to do something which should be more intuitive on iOS.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top