Я пытаюсь применить анимацию вращения по количеству градусов к UIImageView и сохранить преобразование вращения в блоке завершения.
Проблема, с которой я сталкиваюсь, заключается в том, что при выполнении блока завершения появляется видимое мерцание, генерируемое переходом от конечного состояния анимации к блоку завершения.
Вот код, который я сейчас использую:
if (futureAngle == currentAngle) {
return;
}
float rotationAngle;
if (futureAngle < currentAngle) {
rotationAngle = futureAngle - currentAngle;
}else{
rotationAngle = futureAngle - currentAngle;
}
float animationDuration = fabs(rotationAngle) / 100;
rotationAngle = GLKMathDegreesToRadians(rotationAngle);
[CATransaction begin];
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.byValue = [NSNumber numberWithFloat:rotationAngle];
rotationAnimation.duration = animationDuration;
rotationAnimation.removedOnCompletion = YES;
[CATransaction setCompletionBlock:^{
view.transform = CGAffineTransformRotate(view.transform, rotationAngle);
}];
[view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
[CATransaction commit];
Ответ 1 · рейтинг 19 · Rob
Когда вы говорите мерцание, я полагаю, вы имеете в виду, что в конце анимации она на мгновение возвращается в исходное состояние, прежде чем вернуться в конечное состояние? Это можно решить либо путем
- установка конечного
view.transform перед тем, как вы начнете анимацию (и вам больше не нужен completeBlock);
- установив
fillMode анимации на kCAFillModeForwards и установив removedOnCompletion на false.
Лично я считаю, что установка анимированного свойства в его целевое значение до запуска анимации - это самый простой способ сделать это.
Таким образом:
- (void)rotate:(UIView *)view by:(CGFloat)delta {
float animationDuration = 2.0;
CGFloat currentAngle = self.angle; // retrieve saved angle
CGFloat nextAngle = self.angle + delta; // increment it
self.angle = nextAngle; // save new value
view.transform = CGAffineTransformMakeRotation(nextAngle); // set property to destination rotation
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; // now rotate
rotationAnimation.fromValue = @(currentAngle);
rotationAnimation.toValue = @(nextAngle);
rotationAnimation.duration = animationDuration;
rotationAnimation.removedOnCompletion = YES;
[view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
Или, думаю, еще проще, просто настроить transform:
- (void)rotate:(UIView *)view by:(CGFloat)delta {
float animationDuration = 2.0;
CGAffineTransform transform = view.transform; // retrieve current transform
CGAffineTransform nextTransform = CGAffineTransformRotate(transform, delta); // increment it
view.transform = nextTransform; // set property to destination rotation
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; // now rotate
rotationAnimation.fromValue = [NSValue valueWithCGAffineTransform:transform];
rotationAnimation.toValue = [NSValue valueWithCGAffineTransform:nextTransform];
rotationAnimation.duration = animationDuration;
rotationAnimation.removedOnCompletion = YES;
[view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
Ответ 2 · рейтинг 3 · Fonix
Я видел мерцание даже при использовании предложенного ответа Роба, но оказалось, что это просто ошибка симулятора. На реальных устройствах я не вижу мерцания, если вы тестировали только на симуляторе, попробуйте на реальном устройстве, если вы не хотите тратить часы своей жизни, как я.