CABasicAnimation rotate возвращает в исходное положение

Я вращаю CALayer с помощью CABasicAnimation и работает отлично. Проблема в том, что когда я пытаюсь повернуть тот же слой, он возвращается в исходное положение, прежде чем он будет вращаться. Мой ожидаемый результат заключается в том, что для следующего поворота он должен начинаться с того места, где он закончился. Вот мой код:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.fromValue         = 0;
animation.toValue           = [NSNumber numberWithFloat:3.0];
animation.duration          = 3.0;
animation.timingFunction    = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.removedOnCompletion = NO;
animation.fillMode          = kCAFillModeForwards;
animation.autoreverses      = NO;
[calayer addAnimation:animation forKey:@"rotate"];

Чего-то не хватает в моем коде? Спасибо

2 ответа

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

Это действительно стоит прочитать "Базовую архитектуру рендеринга анимации". В противном случае это может быть очень запутанным.

Чтобы это исправить, установите делегата на ваш CABasicAnimation следующее:

[animation setDelegate:self];

Затем создайте метод для установки целевых свойств, которые вы хотите, когда анимация завершится. Теперь вот запутанная часть. Вы должны сделать это на animationDidStart не animationDidStop, В противном случае анимация слоя презентации завершится, и вы увидите мерцание, когда увидите calayer в исходном положении он переходит - без анимации - в целевое положение. Попробуйте это с animationDidStop и вы поймете, что я имею в виду.

Я надеюсь, что это не слишком смущает!

- (void)animationDidStart:(CAAnimation *)theAnimation
{
    [calayer setWhateverPropertiesExpected];
}

РЕДАКТИРОВАТЬ:

Позже я обнаружил, что Apple рекомендует гораздо лучший способ сделать это.

Олег Бегеманн имеет хорошее описание правильной техники в своем посте в блоге. Не допускайте привязки слоев к исходным значениям при использовании явных CAAnimations.

В основном, перед тем, как запустить анимацию, вы запоминаете текущее значение слоя, то есть исходное значение:

// Save the original value
CGFloat originalY = layer.position.y;

Затем установите toValue для модели слоя. Поэтому модель слоя имеет окончательное значение любой анимации, которую вы собираетесь сделать:

// Change the model value
layer.position = CGPointMake(layer.position.x, 300.0);

Затем вы устанавливаете анимацию так, чтобы анимация fromValue была тем оригинальным значением, которое вы отметили выше:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];

// Now specify the fromValue for the animation because
// the current model value is already the correct toValue
animation.fromValue = @(originalY);
animation.duration = 1.0;

// Use the name of the animated property as key
// to override the implicit animation
[layer addAnimation:animation forKey:@"position"];

Обратите внимание, что код для редактирования выше был скопирован / вставлен из блога Оле Бегеманна для ясности

Если вы хотите, чтобы анимация начиналась с того места, где она закончилась, установите fromValue собственность на CALayerТекущее вращение.

Получить это значение непросто, но в этом посте ТАК показано, как: /questions/2103333/calayer-s-animatsiej-vrascheniya/2103346#2103346

Другие вопросы по тегам