Изменение скорости CALayer в CABasicAnimation при вращении колеса вызывает эффект рывка

Я разрабатываю приложение, которое требует, чтобы колесо вращалось вокруг оси z при постоянном увеличении или уменьшении скорости колеса. Я использую CABasicAnimation и мой код выглядит следующим образом. Хотя я изменяю свойство скорости слоя на определенном интервале, это вызывает эффект "рывка" для колеса.

/****/

CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.toValue = [NSNumber numberWithFloat:-2*M_PI];
animation.duration = 4.0f;
animation.repeatCount = INFINITY;
[animation setValue:@"left" forKey:@"side"];
[animation setDelegate:self];
animation.removedOnCompletion=NO;
animation.fillMode = kCAFillModeForwards;
animation.cumulative = YES;

imageLeft.layer.beginTime = CACurrentMediaTime();
/************/

В таймере я изменяю скорость CALayer вида изображения следующим образом, где dPlayedPercentage является переменной.

imageLeft.layer.speed=1.0+dPlayedPercentage;

[imageLeft.layer addAnimation:animation forKey:@"SpinAnimation"];

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

2 ответа

Решение

Добавление следующего кода исправило рывок в анимации.

imageLeft.layer.timeOffset = [imageLeft.layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
imageLeft.layer.beginTime = CACurrentMediaTime(); 
imageLeft.layer.speed=1.0+dPlayedPercentage;

Для более динамического изменения скорости у меня есть некоторые проблемы с предыдущим ответом (слой не рисуется вообще), так как timeOffset нужно рассчитывать с учетом новой скорости.

(источник https://coveller.com/2016/05/core_animation_timing)

Основная формула для timeOffset является:
timeOffset = CACurrentMediaTime() - ((convertTime - beginTime) x speed)

В коде:

theLayer.speed = newSpeed

let mediaTime = CACurrentMediaTime()

let converedTime = theLayer.convertTime(mediaTime, to: nil)

theLayer.beginTime = mediaTime

let offset = mediaTime - ((converedTime - theLayer.beginTime) * Double(newSpeed))

theLayer.timeOffset = offset
Другие вопросы по тегам