CoreAnimation - Opacity Fade In and Out Animation Not Working

后端 未结 11 1827
悲&欢浪女
悲&欢浪女 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:37

    The core of the problem was not understanding the keyTimes property of a CAKeyframeAnimation. This question clarified it all and set me down the right path:

    What kind of value is keyTime in an CAKeyFrameAnimation?

    0 讨论(0)
  • 2020-12-08 05:38

    This works for me:

     let fadeAnimation = CAKeyframeAnimation(keyPath:"opacity")
     fadeAnimation.beginTime = AVCoreAnimationBeginTimeAtZero + start
     fadeAnimation.duration = duration
     fadeAnimation.keyTimes = [0, 1/8.0, 5/8.0, 1]
     fadeAnimation.values = [0.0, 1.0, 1.0, 0.0]
     fadeAnimation.removedOnCompletion = false
     fadeAnimation.fillMode = kCAFillModeForwards
     layer.addAnimation(fadeAnimation, forKey:"animateOpacity")
     layer.opacity = 0.0
    
    0 讨论(0)
  • 2020-12-08 05:40

    I think you're looking for timeOffset, not beginTime...

    0 讨论(0)
  • 2020-12-08 05:47

    Borrowing from the link mentioned by gamblor87 and adding my comments as explanation.

    //create a fadeInOut CAKeyframeAnimation on opacticy
    CAKeyframeAnimation *fadeInAndOut = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    
    //set duration
    fadeInAndOut.duration = 5.0;
    
    //autoreverses defaults to NO so we don't need this.
    //fadeInAndOut.autoreverses = NO;
    
    //keyTimes are time points on duration timeline as a fraction of animation duration (here 5 seconds).
    fadeInAndOut.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],
                                                      [NSNumber numberWithFloat:0.20],
                                                      [NSNumber numberWithFloat:0.80], 
                                                      [NSNumber numberWithFloat:1.0], nil];
    
    
    //set opacity values at various points during the 5second animation
    fadeInAndOut.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],//opacity 0 at 0s (corresponds to keyTime = 0s/5s)
                                                    [NSNumber numberWithFloat:1.0],//opacity 1 at 1s (corresponds to keyTime = 1s/5s)
                                                    [NSNumber numberWithFloat:1.0],//opacity 1 upto 4s (corresponds to keyTime = 4s/5s)
                                                    [NSNumber numberWithFloat:0.0],//opacity 0 at 5s (corresponds to keyTime = 5s/5s)
     nil];
    
    //delay in start of animation. What we are essentially saying is to start the 5second animation after 1second.
    fadeInAndOut.beginTime = 1.0;
    
    //don't remove the animation on completion.
    fadeInAndOut.removedOnCompletion = NO;
    
    //fill mode. In most cases we won't need this.
    fadeInAndOut.fillMode = kCAFillModeBoth;
    
    //add the animation to layer
    [titleLayer addAnimation:fadeInAndOut forKey:nil];
    
    0 讨论(0)
  • 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

    0 讨论(0)
  • 2020-12-08 05:54

    LenK's answer worked perfectly for me. If anyone is interested, I re-wrote for Obj-C (note I also slightly changed the key frames on fade in):

    CAKeyframeAnimation *fadeInAndOutAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    fadeInAndOutAnimation.beginTime = CACurrentMediaTime() + beginTime;
    fadeInAndOutAnimation.duration = duration;
    fadeInAndOutAnimation.keyTimes = @[@0.0, @( 2.0 / 8.0 ), @( 5.0 / 8.0 ), @1.0];
    fadeInAndOutAnimation.values = @[@0.0, @1.0, @1.0, @0.0];
    fadeInAndOutAnimation.removedOnCompletion = false;
    fadeInAndOutAnimation.fillMode = kCAFillModeForwards;
    
    0 讨论(0)
提交回复
热议问题