Почему анимация пользовательских свойств CALayer приводит к тому, что другие свойства становятся нулевыми во время анимации? - PullRequest
16 голосов
/ 25 октября 2010

У меня есть пользовательский 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: вызывается, как и ожидалось, во время анимации, чтобы перерисовать круг, однако оттенок устанавливается равным нулю, как только анимация начинается, и возвращается к своему первоначальному значению, когда анимация заканчивается.

Я пришел к выводу, что если я хочу анимировать пользовательское свойство и хочу, чтобы другие свойства сохраняли свое значение во время анимации, я должен также анимировать их, что я считаю не совсем удобным.

цель не в том, чтобы увеличить / уменьшить круг, я знаю, что могу использовать трансформацию для этого.Это только для того, чтобы проиллюстрировать на простом примере проблему анимации одного пользовательского свойства без необходимости анимировать все остальные.

Я сделал простой проект, иллюстрирующий проблему, которую вы можете найти здесь: Пример проекта, иллюстрирующего проблему

Возможно, что-то, чего я не понял, о том, как работает CoreAnimation, я провел интенсивный поиск, но застрял без подсказки.Кто-нибудь знает?

Ответы [ 2 ]

25 голосов
/ 25 октября 2010

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

0 голосов
/ 25 октября 2010
+ (BOOL)needsDisplayForKey:(NSString *)key {
    if ([key isEqualToString:@"radius"] || [key isEqualToString:@"tint"]) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

Для анимации могут потребоваться все свойства контекста для ответа на обновление.

...