CALayer从当前值淡出

时间:2012-04-18 21:56:54

标签: objective-c cocoa-touch core-animation calayer

我的应用使用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动画中使用)?

干杯。

3 个答案:

答案 0 :(得分:2)

图层的动画只是图层在动画时应该是什么样子的直观表示。在CA中,当您从一个状态动画到另一个状态时,图层的整个状态会立即更改。创建表示层并显示动画,当动画完成时,实际图层将在最后保留。

所以,我的猜测是,当你想从一个状态转换到另一个状态,并且当前动画尚未完成时,你必须捕获动画的当前状态然后使用这是下一个动画的起点。

问题在于无法修改图层的当前动画。

在下面的文章中,我捕获动画的当前状态,将其设置为图层的当前状态,并将其用作动画的起始值。该帖子将此技术应用于动画的速度/持续时间,但也可以应用于您的场景。

https://stackoverflow.com/a/9544674/1218605

答案 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在最近的操作系统版本中将此行为更改为无操作(如果不存在当前事务,则会更加安全),而不更新文档。