Using CAMediaTimingFunction to calculate value at time (t)

beziercore-animation

In Cocoa/Touch, CAMediaTimingFunction represents four control points that specify a cubic bezier curve of a timing function. For an application I am writing I would like to be able to extract the result of said bezier curve at an arbitrary time t (0 -> 1). What is confusing me is that when I look up how to do this, the result is supposed to be a point as well, not a scalar:

B(t) = (1 - t) ^ 3 * P0 + 3 * (1 - t) ^ 2 * t * P1 + 3 * (1 - t) * t ^ 2 * P2 + t ^ 2 * P3

However, Apple's implementation results in a scalar value (you can see on this graph they plot x(t) vs t: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Animation_Types_Timing/Articles/Timing.html#//apple_ref/doc/uid/TP40006670-SW1 )

So does Apple simply ignore the y coordinate of the result and only deal with the x? This seems strange because then you wouldn't need to pass in control points but rather control scalars as the y's wouldn't influence the result at all.

Best Answer

CoreAnimation's CAMediaTimingFunction does what you want but doesn't expose getting 'y' for a given 'x' for versatile (animation) use but rather just feeds the solved values opaquely to the animation system under the hood.

I needed it myself so built a class with the interface and capabilities exactly like CAMediaTimingFunction but with the needed -valueForX: method; usage example:

RSTimingFunction *heavyEaseInTimingFunction = [RSTimingFunction timingFunctionWithControlPoint1:CGPointMake(0.8, 0.0) controlPoint2:CGPointMake(1.0, 1.0)];
CGFloat visualProgress = [heavyEaseInTimingFunction valueForX:progress];

You can create ease-in, ease-out, ease-in-ease-out or really any curves that can be described with a cubic Bézier curve. The implementation math is based on WebCore (WebKit), which is presumably what CoreAnimation is using under the hood too.

Enjoy, Raphael

Related Topic