5

我的应用程序用于CALayer绘制视图。更准确地说,它drawLayer:inContext:在 aUIView的顶层的子层上使用​​该方法。这是让连续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 秒触发另一个渐变到黑色的场景。动画将开始从黑色渐变为白色,但是当它处于“半灰色”时,它会跳到全白,然后再次渐变为黑色。

有没有办法防止这种情况发生?我可以让图层从灰色变回黑色吗?有没有相当于说的 CALayer 绘图UIViewAnimationOptionBeginFromCurrentState(在 UIView 动画中使用)?

干杯。

4

3 回答 3

2

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

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

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

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

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

于 2012-04-28T17:06:15.987 回答
1

我对这个也有点难过。

您是否忘记指定 fillMode kCAFillModeForwards在参考文档中有更多信息。

例如,尽管我没有更改持续时间,但我让它在没有任何捕捉的情况下工作。

@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

但是,您可能希望为自定义属性设置动画。

希望这可以帮助 :/

于 2012-04-27T14:43:43.507 回答
0

我想用层树的缩放动画来完成同样的事情。我有一个放大/缩小键等效项,用户可以相应地缩放图层树。但是,如果用户快速连续按下等效缩放键,则将临时快速恢复到动画开始之前的值,因为之前的动画尚未完成。

在动画代码的最后,执行一个单一的[CATransaction commit]强制所有未决事务在下一个动画开始之前提交到层模型,并解决了问题。

文档说:

+ 提交

提交当前事务期间所做的所有更改。

宣言

+(无效)提交

特别注意事项

如果当前不存在事务,则引发异常。

但是,[CATransaction commit]连续使用许多消息对此进行测试实际上并不会引发异常。我使用了同样的技术来压制表单的警告:

CoreAnimation:警告,删除了未提交 CATransaction 的线程;

在 NSOperation 中,其执行线程在层动画之前完成。如果当前不存在交易,Apple 可能会在最近的操作系统版本中将此行为更改为无操作(这会更明智),而不更新文档。

于 2015-09-17T00:03:00.580 回答