CoreAnimation - Opacity Fade In and Out Animation Not Working

后端 未结 11 1870
悲&欢浪女
悲&欢浪女 2020-12-08 05:02

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

11条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-08 05:53

    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

提交回复
热议问题