I'm animating a view between two points using UIViewAnimationCurveLinear, so I know the velocity of this animation. In certain circumstances I want to append a UIViewAnimationCurveEaseOut to make the view slow to a stop. To make this effect seamless, the ease-out animation must start at the same velocity as the linear animation that preceded it. Given a fixed distance over which I want this easing to occur, how can I compute the duration necessary to achieve this known starting velocity?

For example, let's say I'm animating my view from x = 0 to x = 100 over 10 seconds. The velocity is therefore 10 pixels / second. I now want the view to decelerate from x = 100 to x = 120 using a UIViewAnimationCurveEaseOut animation. What duration should this animation be to ensure that it starts at 10 pixels / second?

It's my understanding that Core Animation's CAMediaTimingFunction controls animation pacing using cubic Bezier curves, where the second and third control points dictate the shape of the curve. I presume that the UIViewAnimationCurve easing functions are also cubic Bezier curves. If I knew the default control points used by these functions I should be able to work out the formula to compute duration given velocity and distance, but I haven't managed to find these default control points documented anywhere.

2

There are 2 answers

0
Kevin Borders On

You can use a constant (call it BEZIER_INTEGRAL_CONSTANT) that approximates the integral of the Bezier curve for an animation that is 1 second long starting at a velocity of 1 pixel / second. For linear easing, this constant is 0.5. For UIViewAnimationCurveEaseOut, it is approximately 0.7. The formula in terms of the duration is:

duration = distance / (velocity * BEZIER_INTEGRAL_CONSTANT)

For your example, where the distance is 20 pixels and the starting velocity is 10 pixels / second, the duration should be approximately: 20 / (10 * 0.7) = 2.9 seconds.

0
Jason Foreman On

I might not be able to give you a complete answer, but I can point you towards the CAMediaTimingFunction's -getControlPointAtIndex:values: method. That should let you create an EaseOut timing function and then examine it's control points.

I'll also point you towards an article by Matt Gallagher about custom acceleration curves done using CAKeyframeAnimation which might also be of use to you.