ios CoreAnimation - 不透明度淡入淡出动画不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8707104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CoreAnimation - Opacity Fade In and Out Animation Not Working
提问by gamblor87
I'm attempting to create a fairly simple CoreAnimation for use in an AVComposition
. My goal is to create a CALayer
which, through various sublayers, fades a title in and out, then fades in an out images. A slideshow, basically. This is being exported to a .mov using AVAssetWriter
.
我正在尝试创建一个相当简单的 CoreAnimation 以在AVComposition
. 我的目标是创建一个CALayer
,通过各种子层,淡入淡出标题,然后淡入淡出图像。基本上是幻灯片。这将使用 .mov 导出到 .mov AVAssetWriter
。
With help from the WWDC 2011 AVEditDemo, I've been able to get a title and images appearing. The problem is that they are all on screen at the same time!
在 WWDC 2011 AVEditDemo 的帮助下,我已经能够获得标题和图像。问题是它们都同时出现在屏幕上!
I have created each layer with an opacity of 0.0. I have then added an CABasicAnimation
to fade them from 0.0 to 1.0, using the following code:
我创建了不透明度为 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];
The problem seems to be the 'beginTime' property. The "1.0" is meant to be a delay, so it starts 1 second after the start of the animation. However, it is appearing on the screen straight away. A fade out animation
问题似乎是 'beginTime' 属性。“1.0”是一个延迟,所以它在动画开始后 1 秒开始。但是,它立即出现在屏幕上。淡出动画
The reverse of this code, for the fade out, simply changes the fromValue to 1.0 and the toValue to 0.0. It has a begin time of 4.0 and works perfectly.
与此代码相反,对于淡出,只需将 fromValue 更改为 1.0,将 toValue 更改为 0.0。它的开始时间为 4.0,并且运行良好。
I'm using the following to create the animatedTitleLayer
:
我正在使用以下内容来创建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;
The image fade in animations have a beginTime 5 seconds apart. Like the title, their fade out animations work fine.
图像淡入动画的 beginTime 间隔为 5 秒。就像标题一样,它们的淡出动画效果很好。
Any help would be greatly appreciated!
任何帮助将不胜感激!
Cheers!
干杯!
EDIT
编辑
The answers were all helpful, but ultimately I discovered that only one animation could be added to a CALayer
. The fade out animation was working as it was the last one added.
答案都很有帮助,但最终我发现只能将一个动画添加到CALayer
. 淡出动画正在工作,因为它是最后一个添加的。
I then tried a CAAnimationGroup, but this didn't work as I was modifying the same key value path.
然后我尝试了 CAAnimationGroup,但这不起作用,因为我正在修改相同的键值路径。
So I've realised that a CAKeyframeAnimation
is the best for this. Only I'm having some difficulty with that too! The code is now fading in okay, but it isn't fading out. I've tried various fillMode's, changed the duration, etc. Can't make it work!!
所以我意识到 aCAKeyframeAnimation
是最好的。只有我也有一些困难!代码现在可以淡入了,但并没有淡出。我尝试了各种填充模式,改变了持续时间等。不能让它工作!!
Here is my code:
这是我的代码:
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];
回答by comonitos
I'm faced the same issue and the problem is - one layer can't contain fade in and out. So you can add the other animation to the parent layer as i did
我面临同样的问题,问题是 - 一层不能包含淡入淡出。所以你可以像我一样将其他动画添加到父层
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];
回答by Mikhail Larionov
Man, so many complicated answers. The simplest way is just to add autoreverse. Voila.
伙计,这么多复杂的答案。最简单的方法就是添加 autoreverse。瞧。
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"];
回答by LenK
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
回答by SayeedHussain
Borrowing from the link mentioned by gamblor87 and adding my comments as explanation.
借用 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];
回答by Den
The point is key name. You have to set the opacity key.
点是键名。您必须设置不透明度键。
layer.add(animation, forKey: nil) // Not Working
layer.add(animation, forKey: "opacity") // Working
Check the sample code. I tested in Swift 4
检查示例代码。我在 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")
回答by WINSergey
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 allin 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:
另一种方法是使用 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];
}
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.
这里关于AVVideoCompositionCoreAnimationTool
. 你可以看到相关的gif图片(标题应该一一出现和消失)。为了解决这个问题,我使用了 2 个单独的CALayer
's 因为出于某种原因,多层上的第 2 层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];
}
}
回答by Ryan
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):
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;
回答by Peter DeWeese
Try:
尝试:
fadeInAnimation.beginTime = CACurrentMediaTime()+1.0;
回答by nielsbot
I think you're looking for timeOffset
, not beginTime
...
我认为你正在寻找timeOffset
,而不是beginTime
......
回答by gamblor87
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:
问题的核心是不理解 CAKeyframeAnimation 的 keyTimes 属性。这个问题澄清了这一切,让我走上了正确的道路: