CoreAnimation – 不透明度淡入和淡出animation不工作

我正在试图创build一个相当简单的CoreAnimation在AVComposition使用。 我的目标是创build一个CALayer ,通过各个子层,淡入淡出标题,然后淡入淡出图像。 幻灯片,基本上。 这是使用AVAssetWriter导出到.mov。

在WWDC 2011 AVEditDemo的帮助下,我已经能够得到一个标题和图像出现。 问题是他们都在同一时间在屏幕上!

我创build了不透明度为0.0的每个图层。 然后我使用下面的代码添加了一个CABasicAnimation使它们从0.0到1.0淡出:

 CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; fadeInAnimation.fromValue = [NSNumber numberWithFloat:0.0]; fadeInAnimation.toValue = [NSNumber numberWithFloat:1.0]; fadeInAnimation.additive = NO; fadeInAnimation.removedOnCompletion = YES; fadeInAnimation.beginTime = 1.0; fadeInAnimation.duration = 1.0; fadeInAnimation.fillMode = kCAFillModeForwards; [titleLayer addAnimation:fadeInAnimation forKey:nil]; 

问题似乎是“beginTime”属性。 “1.0”意味着延迟,所以从animation开始1秒后开始。 但是,它直接出现在屏幕上。 淡出animation

这个代码的反面,淡出,只是简单地将fromValue更改为1.0,toValue更改为0.0。 它有一个开始时间4.0和完美的作品。

我正在使用以下来创buildanimatedTitleLayer

 CATextLayer *titleLayer = [CATextLayer layer]; titleLayer.string =self.album.title; titleLayer.font = @"Helvetica"; titleLayer.fontSize = videoSize.height / 6; titleLayer.alignmentMode = kCAAlignmentCenter; titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height / 6); titleLayer.foregroundColor = [[UIColor redColor]CGColor]; titleLayer.opacity = 0.0; 

animation中的图像淡入淡出时间为5秒。 像标题一样,淡出的animation效果很好。

任何帮助将不胜感激!

干杯!

编辑

答案都是有用的,但最终我发现,只有一个animation可以添加到CALayer 。 淡出animation正在工作,因为它是最后一个添加。

然后我尝试了一个CAAnimationGroup,但是这不起作用,因为我正在修改相同的键值path。

所以我意识到一个CAKeyframeAnimation是最好的。 只有我也有一些困难呢! 这个代码现在正在消失,但它并没有消失。 我已经尝试了各种fillMode的,改变了持续时间等。不能让它工作!

这是我的代码:

  CAKeyframeAnimation *fadeInAndOut = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; fadeInAndOut.duration = 5.0; fadeInAndOut.autoreverses = NO; fadeInAndOut.keyTimes = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:4.0], [NSNumber numberWithFloat:5.0], nil]; fadeInAndOut.values = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:0.0], nil]; fadeInAndOut.beginTime = 1.0; fadeInAndOut.removedOnCompletion = NO; fadeInAndOut.fillMode = kCAFillModeBoth; [titleLayer addAnimation:fadeInAndOut forKey:nil]; 

我面临同样的问题,问题是 – 一层不能包含淡入和淡出。 所以你可以像我一样将其他animation添加到父层

 CALayer *parentLayer = [CALayer layer]; CALayer *animtingLayer = [CALayer layer]; //FADE IN CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.beginTime = CMTimeGetSeconds(img.startTime); animation.duration = CMTimeGetSeconds(_timeline.transitionDuration); animation.fromValue = [NSNumber numberWithFloat:0.0f]; animation.toValue = [NSNumber numberWithFloat:1.0f]; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeBoth; animation.additive = NO; [parentLayer addAnimation:animation forKey:@"opacityIN"]; //FADE OUT CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.beginTime = CMTimeGetSeconds(CMTimeAdd(img.passTimeRange.start, img.passTimeRange.duration)); animation.duration = CMTimeGetSeconds(_timeline.transitionDuration); animation.fromValue = [NSNumber numberWithFloat:1.0f]; animation.toValue = [NSNumber numberWithFloat:0.0f]; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeBoth; animation.additive = NO; [animtingLayer addAnimation:animation forKey:@"opacityOUT"]; [parentLayer addSublayer:animtingLayer]; 

男人,这么多复杂的答案。 最简单的方法就是添加自动反向。 瞧。

 CABasicAnimation *fadeInAndOut = [CABasicAnimation animationWithKeyPath:@"opacity"]; fadeInAndOut.duration = 5.0; fadeInAndOut.autoreverses = YES; fadeInAndOut.fromValue = [NSNumber numberWithFloat:0.0]; fadeInAndOut.toValue = [NSNumber numberWithFloat:1.0]; fadeInAndOut.repeatCount = HUGE_VALF; fadeInAndOut.fillMode = kCAFillModeBoth; [titleLayer addAnimation:fadeInAndOut forKey:@"myanimation"]; 

这适用于我:

  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 

尝试:

 fadeInAnimation.beginTime = CACurrentMediaTime()+1.0; 

我想你正在寻找timeOffset ,而不是beginTime

问题的核心是不了解CAKeyframeAnimation的keyTimes属性。 这个问题澄清了这一切,并把我放在正确的道路上:

CAKeyFrameAnimation中的keyTime是什么types的值?

借用gamblor87提到的链接并添加我的评论作为解释。

 //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]; 

Lenk的回答对我来说是完美的。 如果有人有兴趣,我重新写了Obj-C(注意我也稍微改变了淡入淡出的关键帧):

 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; 

关键是名字。 你必须设置不透明的关键。

 layer.add(animation, forKey: nil) // Not Working layer.add(animation, forKey: "opacity") // Working 

检查示例代码。 我在Swift 4中testing过

  let animation = CAKeyframeAnimation() animation.duration = 1.53 animation.autoreverses = false animation.keyTimes = [0, 0.51, 0.85, 1.0] animation.values = [0.5, 0.5, 1.0, 0.5] animation.beginTime = 0 animation.isRemovedOnCompletion = false animation.fillMode = kCAFillModeBoth animation.repeatCount = .greatestFiniteMagnitude layer.add(animation, forKey: "opacity") 

看看我的回答https://stackoverflow.com/a/44204846/667483

总结:要使用beginTime你应该在你的animation对象上设置fillMode为kCAFillModeBackwards

另一种方法是使用CAAnimationGroup。 CAKeyframeAnimation也适用于UI。 此代码可以在用户界面中正常显示animation。 但在AVVideoCompositionCoreAnimationTool 中完全 AVVideoCompositionCoreAnimationTool – 如果需要,请向下滚动。 这不是代码准备复制粘贴,但你可以得到的想法。 另外,你可以添加添加animation到组中:

 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]; } 

这里有关AVVideoCompositionCoreAnimationTool图层的小animation。 你可以看到相关的gif图像(标题应该一个接一个地出现和消失)。 为了解决这个问题,我使用了2个单独的CALayer ,因为出于某种原因,在多个图层上的一个图层2 opaqueanimation会出现问题。

AVVideoCompositionCoreAnimationTool

 // 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]; } } 

最后,我们可以得到适当的animation序列 正确的动画