2010-10-25 50 views
13

我有一个自定义CALayer(说CircleLayer),包含自定义属性(半径和色调)。该图层在drawInContext:方法中呈现自身。为什么动画自定义CALayer属性导致其他属性在动画过程中为零?

- (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:在动画过程中如预期被调用重新绘制圆形,但是一旦动画开始,色彩设置为零,并在动画结束时恢复到其原始值。

我已经得出结论,如果我想动画一个自定义属性,并希望其他属性在动画期间保持其值,我必须为它们设置动画效果,我觉得这不是很方便。

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

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

有可能是什么我没上CoreAnimation如何工作搞定了,我已经进行了深入的搜索,但我米坚持不了。有谁知道?

回答

24

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

+1

完美你是对的,解决了这个问题!非常感谢:) – romrom 2010-10-25 16:30:21

+0

不客气! – Costique 2010-10-25 16:31:37

+0

这真的很有用。它为我节省了一天的时间。 – feihu 2015-05-19 02:36:06

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

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

+0

我已经试过了,它没有效果。 – romrom 2010-10-25 16:21:12