Jumpy CADDisplayLink Animation

Как подробно описано в предыдущем сообщении (здесь), я создаю анимацию, которая начинается под начальным углом и движется к конечному углу. Я решил использовать CADisplayLink для этой анимации, потому что анимация должна работать как можно быстрее во время пользовательского ввода, поэтому CALayer с CAKeyframeAnimation казалось бы слишком медленным для достижения этого.

После реализации CADisplayLink, который вызывает setNeedsDisplay, анимация работает, но выглядит очень плохо, потому что разбивает разницу между endAngle и initialAngle на хорошо видимые блоки углов вместо того, чтобы создавать непрерывный поток от одного угла к другому. Вот текущий код, который у меня есть:

CGFloat newAngleToAnimate = animationProgress + ((endAngle-initialAngle)/kDrawDuration)*elapsedTime;

// Use newAngleToAnimate to draw in drawInContext

animationProgress = newAngleToAnimate; // Update the progress for the next frame.

Кроме того, kDrawDuration определяется как 3.0f, поэтому я хочу, чтобы анимация от initialAngle до endAngle занимала 3,0 секунды. Я разбиваю полный круг (2*M_PI радиан) на равные сегменты, вычисляя 2*M_PI / kNumAnglesInAnimation, и предпочтительно я хочу анимировать один из этих углов в каждом кадре, но каким-то образом мне все еще приходится учитывать kDrawDuration и elapsedTime, чего я просто не вижу как добиться.

Спасибо за любую помощь в исправлении этого!


person J Kagney    schedule 24.06.2013    source источник


Ответы (1)


CGFloat newAngleToAnimate = animationProgress + ((endAngle-initialAngle)/kDrawDuration)*elapsedTime;

не отслеживать "animationProgress". Ваше elapsedTime — это все, что вам нужно, чтобы ваша анимация была правильной. Так что просто удалите его и используйте:

CGFloat newAngleToAnimate = ((endAngle-initialAngle)/kDrawDuration)*elapsedTime;

person escrafford    schedule 24.06.2013
comment
Я пробовал это, и он не анимируется должным образом. Я должен отметить, что я использую следующий расчет для elapsedTime: CFTimeInterval elapsedTime = _displayLink.timestamp - lastDrawTime; Спасибо, однако. - person J Kagney; 24.06.2013
comment
вам нужно отслеживать время с момента начала рисования (время первого рисования), а не с момента последнего рисования (lastDrawTime) - person escrafford; 24.06.2013
comment
Интересно, спасибо, я попробую это и сообщу вам, как это работает! - person J Kagney; 24.06.2013
comment
Так что это работает, но все еще выглядит очень коренастым в отношении того, как он движется, что заставляет меня задуматься, не связано ли это с вычислением newAngleToAnimate. Если я делю 2pi, скажем, на 300 различных секций с одинаковым углом между каждой секцией, есть ли какая-то настройка, которую я должен установить для CADisplayLink, например frameInterval, чтобы она не работала как можно быстрее или что-то в этом роде? - person J Kagney; 24.06.2013
comment
Я думаю, что понял, в чем проблема: у меня была одинаковая продолжительность анимации независимо от того, какой был endAngle-initialAngle. Таким образом, это выглядит идеально, когда endAngle-initialAngle меньше примерно 2pi/3, но после этого продолжительность анимации становится слишком короткой, чтобы хорошо выглядеть для больших endAngles. Поэтому я думаю, что в конечном итоге я сделаю переключатель, чтобы установить продолжительность для разных частей моего круга. - person J Kagney; 24.06.2013
comment
Да, я могу подтвердить, что выполнение CGFloat duration = 1.0*endAngleSection; где endAngleSection - целое число, работает отлично. Спасибо за помощь! - person J Kagney; 24.06.2013