2010-10-25 1 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, я выполняется интенсивный поиск, но я m застрял без подсказки. Кто-нибудь знает?

ответ

24

Если я правильно понял ваш вопрос, все будет так. Когда вы добавляете анимацию в CALayer, она создает так называемую копию презентации этого слоя, используя initWithLayer:. Уровень презентации содержит фактическое анимированное состояние для каждого кадра анимации, тогда как исходный уровень имеет конечное состояние. Проблема с анимацией ваших собственных свойств заключается в том, что CALayer не копирует их все в initWithLayer:. Если это ваш случай, вы должны переопределить initWithLayer: и настроить все свойства, необходимые для анимации, то есть как оттенок, так и радиус.

+1

Отлично, вы правы, что решили проблему! Большое спасибо :) – romrom

+0

Добро пожаловать! – Costique

+0

Это действительно полезно. Это спасло меня день. – feihu

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

Анимация может потребовать, чтобы все свойства контекста отвечали на обновление.

+0

Я уже пробовал это, и это не имеет никакого эффекта. – romrom

Смежные вопросы