CALayer 从当前值淡出
Posted
技术标签:
【中文标题】CALayer 从当前值淡出【英文标题】:CALayer fade from current value 【发布时间】:2012-04-18 21:56:54 【问题描述】:我的应用使用CALayer
来绘制视图。更准确地说,它在UIView
的顶层的子层上使用drawLayer:inContext:
方法。这是让连续drawLayer:inContext:
绘图的“隐式”动画随着时间的推移逐渐淡入彼此的好方法。渐变动画发生得相当快,可能在 0.25 秒内,但要更改其持续时间,只需实现另一个名为 actionForLayer:forKey:
的委托方法。在这个完美运行的示例实现中,默认持续时间延长到 2.0 秒:
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
animation.duration = 2.0;
return animation;
// or return nil for the default duration.
关于手头的问题。
如果您调用[sublayer setNeedsDisplay]
的速度快于淡入淡出完成的时间,那么每次新的淡入淡出您都会看到突然跳跃。从外观上看,正在进行的淡入淡出被取消,其最终状态被用作新淡入淡出的起点。这可能不是很令人惊讶,但视觉效果是相当不受欢迎的。
考虑从黑色到白色的 10 秒渐变,然后在开始 5 秒后触发另一个渐变到黑色的场景。动画将开始从黑色渐变为白色,但当它处于“半灰色”时,它会跳到全白,然后再次渐变为黑色。
有没有办法防止这种情况发生?我可以让图层从灰色变回黑色吗?有没有相当于 UIViewAnimationOptionBeginFromCurrentState
的 CALayer 绘图(用于 UIView 动画)?
干杯。
【问题讨论】:
【参考方案1】:层的动画只是层在动画时应该是什么样子的视觉表示。在 CA 中,当您从一种状态动画到另一种状态时,图层的整个状态会立即更改。创建一个表示层并显示动画,当动画完成时,实际层留在最后。
所以,我的猜测是,当你想从一种状态过渡到另一种状态,而当前动画还没有完成时,你必须捕获动画的当前状态,然后使用这是您下一个动画的起点。
问题在于无法修改图层的当前动画。
在下面的文章中,我捕获了动画的当前状态,将其设置为图层的当前状态,并将其用作动画的起始值。该帖子将此技术应用于动画的速度/持续时间,但也可以应用于您的场景。
https://***.com/a/9544674/1218605
【讨论】:
P.S.这篇文章帮助我找到了我正在开发的 API 中的一个错误......谢谢。【参考方案2】:我也对这个有点难过。
您是否忘记指定填充模式kCAFillModeForwards
。有更多关于 in the reference docs 的信息。
例如,虽然我没有更改持续时间,但我让它在没有任何捕捉的情况下工作。
@implementation FadingLayer
- (void)fadeOut
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
animation.fillMode = kCAFillModeForwards;
animation.fromValue = (id)[UIColor redColor].CGColor;
animation.toValue = (id)[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
animation.removedOnCompletion = FALSE;
animation.delegate = self;
[self addAnimation:animation
forKey:@"test"];
- (void)fadeIn
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
animation.fillMode = kCAFillModeForwards;
animation.fromValue = (id)[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
animation.toValue = (id)[UIColor redColor].CGColor;
animation.removedOnCompletion = FALSE;
animation.delegate = self;
[self addAnimation:animation
forKey:@"test"];
@end
不过,您可能想要为 a custom property 制作动画。
希望这会有所帮助:/
【讨论】:
因为我使用的是drawLayer:inContext:
,其中的淡入淡出是隐式动画的,所以设置 kCAFillModeForwards 属性没有帮助。感谢您的尝试!【参考方案3】:
我想用层树的缩放动画来完成同样的事情。我有一个放大/缩小键等效项,用户可以相应地缩放图层树。但是,如果用户快速连续按下等效的缩放键,则会暂时恢复到动画开始之前的值,因为之前的动画尚未完成。
在动画代码的最后,执行一个单一的[CATransaction commit]
强制所有未决事务在下一个动画开始之前提交到层模型,并解决了问题。
文档说:
+ 提交
提交当前事务期间所做的所有更改。
声明
+(无效)提交
特别注意事项
如果当前不存在事务,则引发异常。
但是,连续使用许多[CATransaction commit]
消息对此进行测试实际上并不会引发异常。我使用了同样的技术来消除表单的警告:
CoreAnimation:警告,删除未提交的线程 CATransaction;
在 NSOperation 中,其执行线程在层动画之前完成。如果当前不存在交易,Apple 可能会在最近的操作系统版本中将此行为更改为无操作(这会更明智),而不更新文档。
【讨论】:
以上是关于CALayer 从当前值淡出的主要内容,如果未能解决你的问题,请参考以下文章
修复 UIScrollView 顶部和底部的 CALayer