There are almost all identical. The only difference between them is the number of times the change is multiplied by itself. If, for example, a particular point in an animation with easeOut should yield a position [1] of say 0.9 (so 90% of the way through the tween), you’d multiple that 0.9 by itself once for every “power” of the ease. So if the method had a power of 3, it’d be 0.9 * 0.9 * 0.9 = 0.729, instead of 0.9. This means it’d be more “dramatic” – for easeIn, it’d be faster in the beginning and slower at the end.

Those five standard Classes use a power of 1 – 5.

Linear = 1 (and any number to the power of 1 is itself, so at 10% of the way through the tween, the property will have added 10% of the total difference between start and end).
Quad = 2
Cubic = 3
Quart = 4
Quint and Strong = 5

And yes, Quintic and Strong are the same.

Expo uses a power of 10, but applies some other checks as well, so I don’t include it with the 5 standard classes above.

The other, more exotic easing Classes usually just apply a slightly different Math method – the Sine easing class just applies Math.cos (easeIn) and Math.sin (easeOut), and creates more variation at one end (start for easeIn, end for easeOut), and “flattens” the curve on the other end. Back, Bounce and Elastic offer some more complex algorithms that are beyond the scope of this post, so I’ll move on…

@t is the current time (or position) of the tween. This can be seconds or frames, steps, seconds, ms, whatever – as long as the unit is the same as is used for the total time [3].
@b is the beginning value of the property.
@c is the change between the beginning and destination value of the property.
@d is the total time of the tween.

So let’s break this down. Let’s say you’re tweening an object horizontally across the screen. Let’s state some facts:

– It’s originally at position 50 (so in JS/DOM say it had position:absolute and left:50px… In AS, it’d have element.x = 50;).
– You want to tween it to position 200.
– You want the tween to take 1 second.

At the start of the tween, the values passed to the easing function would be:

The parenthesized portion is the percentage of completion… ellapsed time (t) divided by total duration (t). if 30 milliseconds have ellapsed, and the total duration is 50 milliseconds, 30 / 50 = 0.6, or 60% of the way through the tween. This number what runs your tween, and everything else can be extrapolated from that value.

Back to the example… As stated above, we know that at the start of the tween, c is 150, t is 0, d is 1 and b is 50

so 150 * 0 / 1 + 50 = 50

The element, at the start of the tween, would still be at 50px – no change.

Now let’s see what happens at halfway through the tween:

t = 0.5 (halfway through the tween, so 0.5 of 1 second)
b = 50 (the beginning value of the property being tweened)
c = 150 (the change in value – so the destination value of 200 minus the start value of 50 equals 150)
d = 1 (total duration of 1 second)

You’ll see that only the “t” parameter changed – the original value, change in value, and total duration are all unchanged. Let’s see how the change to the ellapsed time affects the return.

The formula is the same: c * t / d + b, but now the updated “t” value (ellapsed time) has changed, so

150 * 0.5 / 1 + 50 = 125

Now the easing function returns 125, positioning the element at top/x of 125. This is indeed halfway between 50 (start) and 200 (end), and shows an increase of 75 pixels from the original value.

Breaking it down a little, we’ll always want to add the beginning value (b). The tween changes the property in relation to that beginning value, so we’ll always be adding that change to “b”

b + ( the relative change )

And we know that t / d represents the percentage

so 0.5 / 1 = 0.5, or 50%

The total change in value at the end of the tween – the difference between the beginning value and the destination value – is 150 (the “c” parameter)

So 50% of 150 is 75. That’s the relative change at this point in the tween.

Add that relative change (75) to the original value “b” (50), and we get the 125 current position. Simple :)

Again, you’ll also notice that all the magic happens here (highlighted):

c * t / d + b

In almost all easing calculations, it’s always going to be change in propertytimes (some float) plus beginning value. How that float (the highlighted bit above) is calculated determines the returned value for any point during the tween.

In fact, for any tween, you could really just substitute @b and @c for 0 and 1, respectively – the return of the function would be a number between 0 and 1. Multiply the difference between the start value and the end value, and add that to the start value, and the effect would be the same.

In fact, you can even omit those parameters from an easing function – the following works almost identically to any of the standard easing Class’s version of easeIn:

1

returnMath.pow(t/d,<power>);

So the function could take just two arguments: start time and total time, where “power” is the number of referenced for each of the Classes (above). To emulate Strong.easeIn, for example, the following function would perform identically:

1

2

3

functioneaseIn(t,d){

returnMath.pow(t/d,5);

}

easeOut is pretty similar:

1

return1-Math.pow(1-(t/d),<power>);

So Strong.easeOut would look like:

1

2

3

functionstrongEaseOut(t,d){

return1-Math.pow(1-(t/d),5);

}

You could even write a very simple functor to have any number greater than those 5, or using floated versions…

1

2

3

4

5

functioneaseOut(v){

returnfunction(t,b,c,d){

return1-Math.pow(1-(t/d),v);

}

}

And it’d be passed as the return of an invocation, rather than a reference. The following psuedo-code shows how to use the concept just above to creating an ease halfway between Quartic and Quintic:

1

SomeTween.performTween(target,duration,props,easeOut(4.5));

You could also use the same concept to customize the easeBack function, to create more or less dramatic returns:

1

2

3

4

5

6

functioneaseBack(v){

if(typeofv=='undefined')v=1.70158;

returnfunction(t,b,c,d){

returnc*((t=t/d-1)*t*((v+1)*t+v)+1)+b;

}

}

[1] The term “position” doesn’t necessarily refer to a dimensional position, it could be any point between the start and end of the tween.[2] I’ll use JS notation throughout, but all sample code here would work identically in AS3, just add datatypes.[3] The current time (“position”) and the total time can be any numbers, and just represent a percentage of change. So frame 5 of 10 is halfway through, the same as 0.5 of 1 seconds, or 3500 of 7000 seconds. As long as both are expressed in the same unit, the actual values don’t matter – any numbers greater than 0 or less than Infinity will serve.

Hi there. First off, great post, but I just wanted to know a small error at the beginning that may have just been an innocent mistake. The error is in this passage:

If, for example, a particular point in an animation with easeIn should yield a position [1] of say 0.9 (so 90% of the way through the tween), you’d multiple that 0.9 by itself once for every “power” of the ease. So if the method had a power of 3, it’d be 0.9 * 0.9 * 0.9 = 0.729, instead of 0.9. This means it’d be more “dramatic” – for easeIn, it’d be faster in the beginning and slower at the end.

I think you mean EaseOut instead of EaseIn here. An EaseIn would start out slow and speed up near the end; it “eases” in to the movement, so to speak. EaseOut, on the other hand starts out fast and then slows down at the end. Otherwise, great page and explanation!

I’m not exactly sure what you mean, or where the code samples you pasted is from. I did not write the easing equations described here, they were originally written by Robert Penner (although a lot of people have ported, translated or otherwise borrowed from that original group of easing equations).

I’m not sure what you mean. The easing function will provide a weighted value between 1 and 0 (or beyond that in the case of bounce and elastic type functions), which can be applied to the total change in property value between a starting value and a destination value. It would not tell the position along a bezier of a display object, although if the easing function were used to set the position, I supposed it could be extrapolated.

It certainly *can* return any number, but in this case the number returned would be a weighted progress – 0 being the very start and 1 being the very end – and even that isn’t entirely consistent, as Back, Bounce and Elastic easing might exceed 1… for example, when Back overshoots by say 15%, that’d be a easing value of either 1.15 (if the easing function is returning a straight weighted progress), or change * 1.15 (if the new value was computed in the easing function)

Well explained. I am looking for a way to do custom easings using Apples new SpriteKit. They only support the most basic ones right now. I want to learn how to tweak ease-calculations and this was a great way to start. Thx!

Yup – great post ! – thanks a lot, it made a lot of things clear to me (especially since my math-level is really quite bad…) I am translating this into python3 and it works pretty well :)
only part I am not 100% sure is:
quote: ” In fact, for any tween, you could really just substitute @b and @c for 0 and 1, respectively – the return of the function would be a number between 0 and 1. Multiply the difference between the start value and the end value, and add that to the start value, and the effect would be the same.”

that quote means that the entire “control” of the tween is the float produced by the math. the penner methods take the beginning value, the change in value, and apply the float to the change and add it to the beginning value. this isn’t always exactly necessary. that float is the crux – with that number you can do whatever you want, and sometimes you actually don’t want to pre-determine the destination value (for example, you might want to “tween” the order of appearance of display objects – so you’d want just the float value, not applied to start or change values.

you can get that float by passing 0 and 1 for @b and @c – this number can be used directly, as in:

… or more indirectly, perhaps applied to a number of different transforms, or applied to a non-standard effect like timing the appearance of words on a page (you could use ease out to have the words appear one-at-a-time, quickly at first, then more slowly as the page fills… that’s just an example, and probably a poor one at that, but my point (as emphasized heavily in the post) is that the calculations performed on “t/d” is really the heart of the tween, and to use inertia in effects outside of straight property tweens, it can be a good idea to separate that bit out entirely, which can be done with 0 and 1 for b and c.

“d” is equal to “duration”, so that’ll always be available from whatever duration you passed to the animation routine (as opposed to the easing routine). generally you’ll want the factor returned from an easy function, so it can be passed to the calculation to determine the position… while i wouldn’t recommend doing so, i suppose you could return an object with properties (including the factor, duration, or anything else you wanted) and use the appropriate property… like so:

1

2

3

4

5

6

7

8

9

10

11

functiongetEaseBackObject(t,b,c,d){

varv=1.70158;

varfactor=c*((t=t/d-1)*t*((v+1)*t+v)+1)+b;

return{

t:t,

b:b,

c:c,

d:d,

factor:factor

}

}

As far as examples… This post is more about understanding existing easing methods, and how you an adapt them. Most folks nowadays use frameworks (all the big JS frameworks include animation methods, including jQuery, MooTooos, Prototype, dojo, YUI, etc), and in ActionScript folks use classes like TweenLite, GTween, Tweeny, Tweensy, etc), but assuming you wanted to build it from scratch, it’s pretty simple. Here’s a quick sample animating a div 500px over 1 second, using the easeIn function outlined above: http://jsfiddle.net/moagrius/gRCkW/

I am trying to adapt Penner’s equations to robotic motion. So thanks for explaining. Two things that are not clear to me. I can’t wrap my head around easeinout. In and out by themselves are simple, but I can’t seem to combine them. Also, Penner’s calculations use the /= operator, and while I understand the concept, I can’t rewrite his equations in a language that doesn’t have this operator. I feel like a dolt to be stumbling on something this simple.

I don’t see anything that looks exactly like what you’ve described, but IIUC then I’d agree with you – multiple tests on the same value do seem redundant. FWIW, the easing functions I keep handy (Penner’s) do see to test appropriately, e.g.,

Penner very helpfully includes one of his book chapters on his web site, which is very generous. But I’m doing something rather different with them, and after reading specific parts repeatedly, I wasn’t able to adapt them. Your explanations are a big help.

Thanks for this helpful post! Every one is aware of easing but, till now no-one did actually explained what goes on in it. I’m trying to smooth rotate a sprite and this would help immensely to understand the process.