CABasicAnimation rotate возвращает в исходное положение - PullRequest
3 голосов
/ 07 октября 2011

Я вращаю 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 ]

16 голосов
/ 07 октября 2011

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

Действительно стоит прочитать «Базовая архитектура рендеринга анимации» .В противном случае это может привести к путанице.

Чтобы исправить это, установите делегата на 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;

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

// 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"];

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

1 голос
/ 20 сентября 2012

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

Получить это значение сложно, но этот пост ТАК показывает, как: https://stackoverflow.com/a/6706604/1072846

...