I\'m attempting to create a fairly simple CoreAnimation for use in an AVComposition
. My goal is to create a CALayer
which, through various sublayer
The alternative way is the using CAAnimationGroup. CAKeyframeAnimation also works fine for UI. This code works fine in UI for show animation real-time. But will not work at all in AVVideoCompositionCoreAnimationTool
- please scroll down if you need it. It is not code ready for copy-paste but you can get the idea. Also, you can add addition animations to the group:
for (HKAnimatedLayer *animLayer in layersList) {
overlayLayer = [CALayer layer];
[overlayLayer setContents:(id)[animLayer.image CGImage]];
overlayLayer.frame = CGRectMake(0, 0, size.width, size.height);
[overlayLayer setMasksToBounds:YES];
NSMutableArray *animations = [NSMutableArray array];
// Step 1
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.toValue = @(0);
animation.duration = kLayerFadeDuration;
animation.beginTime = kMovieDuration/5;
animation.fillMode = kCAFillModeForwards;
[animations addObject:animation];
}
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.toValue = @(1.0);
animation.duration = kLayerFadeDuration;
animation.beginTime = kMovieDuration*2/3;
animation.fillMode = kCAFillModeForwards;
[animations addObject:animation];
}
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = animations;
animationGroup.duration = kMovieDuration;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = YES;
[overlayLayer addAnimation:animationGroup forKey:nil];
[parentLayer addSublayer:overlayLayer];
}
Here small note about animation on layers for AVVideoCompositionCoreAnimationTool
. You can see relevant gif image (titles should appear and disappear one by one). To solve this issue I use 2 separate CALayer
's because for some reason on one layer 2 opaque
animations on multiple layers are glitched.
// set up the parent layer
CALayer *parentLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
// one layer for one animation
CALayer *overlayLayer, *barrierLayer;
CABasicAnimation *animation;
for (HKAnimatedLayer *animLayer in layersList) {
overlayLayer = [CALayer layer];
overlayLayer.contents = (id)[animLayer.image CGImage];
overlayLayer.frame = CGRectMake(0, 0, size.width, size.height);
overlayLayer.masksToBounds = YES;
// layer with appear animation
if (animLayer.fromTime != 0 && (animLayer.fromTime - kLayerFadeDuration)>0) {
overlayLayer.opacity = 0.0;
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = @(0);
animation.toValue = @(1);
animation.additive = NO;
animation.removedOnCompletion = NO;
animation.beginTime = animLayer.fromTime - kLayerFadeDuration;
animation.duration = kLayerFadeDuration;
animation.fillMode = kCAFillModeForwards;
[overlayLayer addAnimation:animation forKey:@"fadeIn"];
}
if (animLayer.toTime == kMovieDuration) {
[parentLayer addSublayer:overlayLayer];
} else { // layer with dissappear animation
barrierLayer = [CALayer layer];
barrierLayer.frame = CGRectMake(0, 0, size.width, size.height);
barrierLayer.masksToBounds = YES;
[barrierLayer addSublayer:overlayLayer];
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = @(1);
animation.toValue = @(0);
animation.additive = NO;
animation.removedOnCompletion = NO;
animation.beginTime = animLayer.toTime;
animation.duration = kLayerFadeDuration;
animation.fillMode = kCAFillModeForwards;
[overlayLayer addAnimation:animation forKey:@"fadeOut"];
[parentLayer addSublayer:barrierLayer];
}
}
And at the end, we can get proper animation sequence