试图将图层的 CABasicAnimation 位置和不透明度延迟 3 秒,但
Posted
技术标签:
【中文标题】试图将图层的 CABasicAnimation 位置和不透明度延迟 3 秒,但【英文标题】:Trying to delay CABasicAnimation position and opacity of layer by 3 seconds but 【发布时间】:2013-01-13 22:40:09 【问题描述】:我正在尝试使用 setBeginTime 将图层不透明度和位置的动画延迟 3 秒。我已经调用了层boxLayer。动画进展顺利,但是在前 3 秒内(该图层还不应显示),图层显示为其最终位置和不透明度。它不应该。组动画不能解决问题。有人可以帮忙吗?见以下代码:
// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// Maintain opacity to 1.0 JUST TO MAKE SURE IT DOES NOT GO BACK TO ORIGINAL OPACITY
[boxLayer setOpacity:endOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// Maintain the end position at 400.0 450.0 OTHERWISE IT IS GOING BACK TO ORIGINAL POSITION
[boxLayer setPosition:CGPointMake(endX, endY)];
【问题讨论】:
如何创建一个类似 [self performSelector:@selector(methodname) withObject:nil afterDelay:3.0f] 的方法;或使用 sleep(); 我的问题不是动画延迟,而是图层在延迟动画开始之前显示。 【参考方案1】:问题是您将position
和opacity
的boxLayer
属性设置为其最终值。您需要:
将boxLayer
属性设置为它们的起始值,而不是它们的结束值(这就是为什么它从结束位置/不透明度开始......通常如果动画立即开始,这不是问题,但是因为你推迟了开始,所以使用结束位置是有问题的);
对于您的两个动画,您必须将removedOnCompletion
更改为NO
并将fillMode
更改为kCAFillModeForwards
(这是防止它在完成后恢复到原始位置的正确方法)。
因此:
// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// MAKE SURE IT DOESN'T CHANGE OPACITY BACK TO STARTING VALUE
[fader setRemovedOnCompletion:NO];
[fader setFillMode:kCAFillModeForwards];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// SET THE OPACITY TO THE STARTING VALUE
[boxLayer setOpacity:startOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// MAKE SURE IT DOESN'T MOVE BACK TO STARTING POSITION
[mover setRemovedOnCompletion:NO];
[mover setFillMode:kCAFillModeForwards];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// SET THE POSITION TO THE STARTING POSITION
[boxLayer setPosition:CGPointMake(startX, startY)];
就个人而言,我认为您正在做很多工作,这些工作在视图上使用基于块的动画更容易完成(出于本演示的目的,我假设您的 boxLayer
是 @987654331 @ 用于名为 box
的控件)。如果你这样做,你也不需要 Quartz 2D:
box.alpha = startOpacity;
box.frame = CGRectMake(startX, startY, box.frame.size.width, box.frame.size.height);
[UIView animateWithDuration:1.0
delay:3.0
options:0
animations:^
box.alpha = endOpacity;
box.frame = CGRectMake(endX, endY, box.frame.size.width, box.frame.size.height);
completion:nil];
【讨论】:
我的问题不在于动画本身的延迟。这样可行。我的问题是要动画的图层(移动和淡入)在动画之前的 3 秒内出现。 是的。就像你说的罗伯。它是“开始可见 3 秒,然后消失并慢慢淡入并在下一秒出现动画”。我在发布的块之前创建了图层。我认为发布所有内容会太长。就像我可以在第一秒显示图层动画时延迟图层动画,或者我可以在没有动画发生时延迟图层的显示。有趣的。我正在使用 setBeginTime 和 Duration 等方法。不是自动布局或 animateWithDuration。有什么想法吗? @user1915931 虽然我认为使用基于块的视图动画要容易得多,但如果您下定决心为图层设置动画,我也已将答案更新为CABasicAnimation
答案.
Rob 我愿意使用基于块的动画,尽管我以前从未这样做过...我会尝试使用您的示例并让您知道。
非常感谢罗伯!!!有用。我也很感谢您提到基于块的动画。我卡在图层上的原因是因为我使用的是 CATextLayer。里面有文字。内容因页面而异。另外,我需要随时翻转它。所以请随时让我知道是否有任何更简单的方法来实现这一切......基于块的动画是否可以处理先前从数据库中提取的嵌入文本,翻转动作?已经谢谢了:-)【参考方案2】:
这篇文章很好地解释了为什么你不应该将 removedOnCompletion 与 fillMode https://www.objc.io/issues/12-animations/animations-explained/一起使用
在我的例子中,我正在为用作导航的视图层设置动画,但会延迟该视图内的反弹动画;我需要在图层上更新这两个位置,因为它可以被解除然后再次显示。动画完成后,使用 removedOnCompletion 不会更新图层的值
我这样做的方法是更新 CATransaction 完成块中的层
CATransaction.setCompletionBlock
// update the layer value
CATransaction.begin()
// setup and add your animation
CATransaction.commit()
【讨论】:
【参考方案3】:要使用beginTime
,您应该对动画对象进行必要的配置,并将fillMode
设置为kCAFillModeBackwards
,如
zoomAnimation.fillMode = kCAFillModeBackwards;
Apple 文档中这么说:
使用 beginTime 属性设置动画的开始时间。通常,动画在下一个更新周期开始。您可以使用 beginTime 参数将动画开始时间延迟几秒钟。将两个动画链接在一起的方法是将一个动画的开始时间设置为与另一个动画的结束时间相匹配。 如果您延迟动画的开始,您可能还需要将 fillMode 属性设置为 kCAFillModeBackwards。这种填充模式会导致图层显示动画的起始值,即使图层树中的图层对象包含不同的值。如果没有这种填充模式,您会在动画开始执行之前看到跳转到最终值。其他填充模式也可用。
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/AdvancedAnimationTricks/AdvancedAnimationTricks.html#//apple_ref/doc/uid/TP40004514-CH8-SW2
另外,来自 Rob 的回答:
对于您的两个动画,您必须将 removedOnCompletion 更改为 NO 并将 fillMode 更改为 kCAFillModeForwards(这是防止它在完成后恢复到原始位置的正确方法。
这是一种有争议的说法,因为:
一旦动画被移除,表示层将回退到模型层的值,并且由于我们从未修改过该层的位置,所以我们的宇宙飞船会重新出现在它开始的位置。 有两种方法可以处理这个问题:
第一种方法是直接在模型层更新属性。这是推荐的方法,因为它使动画完全可选。
或者,您可以通过将其 fillMode 属性设置为 kCAFillModeForwards 来告诉动画保持其最终状态,并通过将 removedOnCompletion 设置为 NO 来防止它被自动删除。但是,保持模型层和表示层同步是一种很好的做法,因此应谨慎使用此方法。
来自https://www.objc.io/issues/12-animations/animations-explained/
【讨论】:
以上是关于试图将图层的 CABasicAnimation 位置和不透明度延迟 3 秒,但的主要内容,如果未能解决你的问题,请参考以下文章