我正在尝试创建一个相当简单的CoreAnimation,以便在AVComposition
中使用。我的目标是创建一个CALayer
,通过各种子图层,淡入淡出标题,然后淡出图像。幻灯片,基本上。这是使用AVAssetWriter
导出到.mov。
在WWDC 2011 AVEditDemo的帮助下,我已经能够获得一个标题和图像。问题是它们同时都在屏幕上!
我创建了不透明度为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”意味着延迟,因此它在动画开始后1秒开始。但是,它会立即出现在屏幕上。淡出动画
此代码的反向,对于淡出,只需将fromValue更改为1.0,将toValue更改为0.0。它的开始时间为4.0,运行良好。
我正在使用以下内容创建animatedTitleLayer
:
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;
动画中的图像淡入时间相差5秒。像标题一样,它们的淡出动画效果很好。
非常感谢任何帮助!
干杯!
修改
答案都很有帮助,但最终我发现只有一个动画可以添加到CALayer
。淡出动画正在运行,因为它是最后添加的动画。
然后我尝试了CAAnimationGroup,但这不起作用,因为我修改了相同的键值路径。
所以我意识到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];
答案 0 :(得分:28)
我遇到了同样的问题,问题是 - 一层不能包含淡入淡出。 所以你可以像我一样将其他动画添加到父图层
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];
答案 1 :(得分:25)
男人,这么多复杂的答案。最简单的方法就是添加自动反转。瞧。
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"];
答案 2 :(得分:2)
这对我有用:
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
答案 3 :(得分:1)
尝试:
fadeInAnimation.beginTime = CACurrentMediaTime()+1.0;
答案 4 :(得分:1)
我认为您正在寻找timeOffset
,而不是beginTime
...
答案 5 :(得分:1)
问题的核心是没有理解CAKeyframeAnimation的keyTimes属性。这个问题澄清了这一切,让我走上了正确的道路:
答案 6 :(得分:1)
借用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];
答案 7 :(得分:1)
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;
答案 8 :(得分:1)
另一种方法是使用CAAnimationGroup。 CAKeyframeAnimation也适用于UI。此代码在UI中可以很好地实时显示动画。但是AVVideoCompositionCoreAnimationTool
中的根本不起作用 - 如果需要,请向下滚动。它不是代码准备好复制粘贴,但你可以得到这个想法。此外,您还可以向该组添加其他动画:
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
图层动画的小注释。您可以看到相关的gif图像(标题应该一个接一个地出现和消失)。要解决此问题,我使用了2个单独的CALayer
,因为出于某种原因,在一个图层上,多个图层上的opaque
个动画会出现故障。
// 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];
}
}
答案 9 :(得分:1)
重点是关键名称。您必须设置不透明度键。
layer.add(animation, forKey: nil) // Not Working
layer.add(animation, forKey: "opacity") // Working
检查示例代码。我在Swift 4中测试过
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")
答案 10 :(得分:0)
看看我的回答https://stackoverflow.com/a/44204846/667483
总结:要使用beginTime
,您应该在动画对象上将fillMode设置为kCAFillModeBackwards
。