我的应用使用CALayer
来绘制视图。更准确地说,它在drawLayer:inContext:
顶层的子图层上使用UIView
方法。这是一种很好的方法,可以让连续的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]
的速度比衰落时间要快,那么每次新的淡入淡出你都会看到突然跳跃。从它的外观来看,正在进行的淡入淡出被取消,它的最终状态被用作新淡入淡出的起点。这可能不是很令人惊讶,但视觉效果是不必要的。
考虑从黑色到白色的十秒钟淡入淡出的情景,在开始后五秒钟触发另一次淡入淡出,变为黑色。动画将从黑色渐变为白色,但当它处于“半灰色”时,它会跳到全白色,然后再次变为黑色。
有没有办法防止这种情况发生?我可以让图层从灰色渐变回黑色吗? CALayer绘图是否相当于说UIViewAnimationOptionBeginFromCurrentState
(在UIView动画中使用)?
干杯。
答案 0 :(得分:2)
图层的动画只是图层在动画时应该是什么样子的直观表示。在CA中,当您从一个状态动画到另一个状态时,图层的整个状态会立即更改。创建表示层并显示动画,当动画完成时,实际图层将在最后保留。
所以,我的猜测是,当你想从一个状态转换到另一个状态,并且当前动画尚未完成时,你必须捕获动画的当前状态然后使用这是下一个动画的起点。
问题在于无法修改图层的当前动画。
在下面的文章中,我捕获动画的当前状态,将其设置为图层的当前状态,并将其用作动画的起始值。该帖子将此技术应用于动画的速度/持续时间,但也可以应用于您的场景。
答案 1 :(得分:1)
我也有点难过这个。
您是否忘记指定fillMode 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设置动画。
希望这会有所帮助:/
答案 2 :(得分:0)
我想用层树的缩放动画完成同样的事情。我有一个放大/缩小键等效,用户可以相应地缩放图层树。但是,如果用户快速连续按下缩放键等效,则会在动画开始之前暂时回显值,因为上一个动画尚未完成。
在动画代码结束时,执行唯一的[CATransaction commit]
强制任何挂起的事务在下一个动画开始之前提交给图层模型,并解决了问题。
文档说:
+ commit
提交当前交易期间所做的所有更改。
<强>声明强>
+(void)commit
特别注意事项
如果不存在当前事务,则引发异常。
但是,连续测试许多[CATransaction commit]
消息并不会引发异常。我使用了同样的技术来压制形式的警告:
CoreAnimation:警告,未提交的已删除线程 CATransaction;
在NSOperation中,其执行线程在图层动画之前完成。可能是Apple在最近的操作系统版本中将此行为更改为无操作(如果不存在当前事务,则会更加安全),而不更新文档。