为什么动画自定义CALayer属性会导致其他属性在动画期间为零?

时间:2010-10-25 16:05:13

标签: iphone animation properties calayer null

我有一个自定义CALayer(比如CircleLayer),包含自定义属性(半径和色调)。该图层在其drawInContext:方法中呈现自身。

- (void)drawInContext:(CGContextRef)ctx {
    NSLog(@"Drawing layer, tint is %@, radius is %@", self.tint, self.radius);

    CGPoint centerPoint = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);

    CGContextMoveToPoint(ctx, centerPoint.x, centerPoint.y);
    CGContextAddArc(ctx, centerPoint.x, centerPoint.y, [self.radius doubleValue], radians(0), radians(360), 0);
    CGContextClosePath(ctx);

    /* Filling it */
    CGContextSetFillColorWithColor(ctx, self.tint.CGColor);
    CGContextFillPath(ctx); 
}

我希望半径可以设置为动画,所以我已经实现了

+ (BOOL)needsDisplayForKey:(NSString *)key {
    if ([key isEqualToString:@"radius"]) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

动画的执行方式如下:

CABasicAnimation *theAnimation=[CABasicAnimation animationWithKeyPath:@"radius"];
theAnimation.duration=2.0;
theAnimation.fromValue=[NSNumber numberWithDouble:100.0];
theAnimation.toValue=[NSNumber numberWithDouble:50.0];
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

[circleLayer addAnimation:theAnimation forKey:@"animateRadius"];

circleLayer.radius = [NSNumber numberWithDouble:50.0];

drawInContext:在动画期间按预期调用以重绘圆圈,但是一旦动画开始,色调就会设置为nil,并在动画结束时恢复到原始值。

我得出结论,如果我想动画一个自定义属性并希望其他属性在动画期间保持其值,我也必须为它们制作动画,我发现它根本不方便。

目的不是增长/缩小一个圆圈,我知道我可以使用转换。它只是用一个简单的例子来说明动画单个自定义属性的问题,而不必为所有其他属性设置动画。

我做了一个简单的项目来说明这个问题,你可以在这里找到: Sample project illustrating the issue

我可能还没有看到CoreAnimation是如何工作的,我已经进行了密集搜索,但我一点都不知道。有人知道吗?

2 个答案:

答案 0 :(得分:25)

如果我理解你的问题,就会这样。将动画添加到CALayer时,它会使用initWithLayer:创建该图层的所谓演示文稿副本。表示层包含每个动画帧的实际动画状态,而原始图层具有最终状态。动画您自己的属性的问题是CALayer不会在initWithLayer:中复制它们。如果是这种情况,你应该覆盖initWithLayer:并设置动画所需的所有属性,即色调和半径。

答案 1 :(得分:0)

+ (BOOL)needsDisplayForKey:(NSString *)key {
    if ([key isEqualToString:@"radius"] || [key isEqualToString:@"tint"]) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

动画可能需要上下文的所有属性才能响应刷新。