DIFFERENT EASING TYPES


So far all our code is looking pretty tight but there's still a little room for improvement. Currently we're only using the Math.pow function to raise the initial ratio to a higher power yet there are many other ways to distort or skew values between 0 and 1 and many of them will produce noticeably different easing results. Here are a few examples for you to consider:

//____________________________________________
//
Math.ezExpo = function (r, p) {
        if(r==0 || r==1) return r;
        if(p<2)p = 2;
        return Math.pow(p, 10*(r-1));
}
Math.ezCirc = function (r, p) {
        r = -(Math.sqrt(1-r*r)-1);
        if(p>1) return Math.easeIn(r, --p, Math.ezCirc);
        return r;
}
Math.ezSine = function (r, p){
        r = 1-Math.cos(r*Math.PI/2);
        if(p>1) return Math.easeIn(r, --p, Math.ezSine);
        return r;
}
//____________________________________________

Explaining how each of the above functions work is a bit beyond the scope of this tutorial but it should be sufficient to say they all have a few things in common, they accept numbers between 0 and 1, the values they return are weighted towards the 0 end of the 0 to 1 spectrum and they all accept a "power" argument which controls the strength of the easing effect. In short, they work just like our Math.pow function but return slightly different results. Incorporating the above functions into our existing easing functions will be one of the last alterations we make:

//____________________________________________
//
Math.easeIn = function (ratio, power, ezFunction){
        if (power == undefined) power = 2;
        if (ezFunction == undefined) ezfunction = Math.pow;
        return ezFunction(ratio, power);
}
Math.easeOut = function(ratio, power, ezFunction){
        return 1-Math.easeIn(1-ratio, power, ezFunction);
}
Math.easeInOut = function (ratio, power, ezFunction){
        if(ratio<.5)return Math.easeIn(2*ratio, power, ezFunction)/2;
        return Math.easeOut(2*(ratio-.5), power, ezFunction)/2+.5;
}
//____________________________________________

As you can see, our "easeIn" function has been modified to accept an alternate easing equation (ezFunction) as a third argument. If you don't declare an alternate easing equation (if ezFunction == undefined) then the standard "Math.pow" function will be used by default. Since both our "easeOut" and "easeInOut" functions make use of our "easeIn" function the only modifications they needed was to make sure they pass "ezFunction" along as an argument for the "easeIn" function.

Our easing functions now have all the features they're ever going to have. Since we won't be making any further modifications, we can sacrifice a little readability for a moderate performance gain by using shorter variable names. Let's put them to the test and see how well they perform.

//____________________________________________
//
// Declare all our Math functions
Math.easeIn = function (r, p, f){
        if (p == undefined) p = 2;
        if (f == undefined) f = Math.pow;
        return f (r, p);
}
Math.easeOut = function(r, p, f){
        return 1-Math.easeIn(1-r, p, f);
}
Math.easeInOut = function (r, p, f){
        if(r<.5)return Math.easeIn(2*r, p, f)/2;
        return Math.easeOut(2*(r-.5), p, f)/2+.5;
}
Math.ezExpo = function (r, p) {
        if(r==0 || r==1) return r;
        if(p<2)p = 2;
        return Math.pow(p, 10*(r-1));
}
Math.ezCirc = function (r, p) {
        r = -(Math.sqrt(1-r*r)-1);
        if(p>1) return Math.easeIn(r, --p, Math.ezCirc);
        return r;
}
Math.ezSine = function (r, p){
        r = 1-Math.cos(r*Math.PI/2);
        if(p>1) return Math.easeIn(r, --p, Math.ezSine);
        return r;
}
// Make four balls
createEmptyMovieClip("Ball1_mc", 10);
with (Ball1_mc) {
        lineStyle(40, 0xFF0000);
        lineTo(.5, 0);
        _x = 50;
        _y = 50;
}
createEmptyMovieClip("Ball2_mc", 20);
with (Ball2_mc) {
        lineStyle(40, 0xFF0000);
        lineTo(.5, 0);
        _x = 50;
        _y = 150;
}
createEmptyMovieClip("Ball3_mc", 30);
with (Ball3_mc) {
        lineStyle(40, 0xFF0000);
        lineTo(.5, 0);
        _x = 50;
        _y = 250;
}
createEmptyMovieClip("Ball4_mc", 40);
with (Ball4_mc) {
        lineStyle(40, 0xFF0000);
        lineTo(.5, 0);
        _x = 50;
        _y = 350;
}
// Declare a variable to track the current frame
currentFrame = 0;
// Move all balls
Ball1_mc.onEnterFrame = function(){
        this._x = 50 + Math.easeInOut(currentFrame/50, 2) * 450;
        if(++currentFrame > 50) delete this.onEnterFrame;
}
Ball2_mc.onEnterFrame = function(){
        this._x = 50 + Math.easeInOut(currentFrame/50, 1, Math.ezSine) * 450;
        if(currentFrame > 50) delete this.onEnterFrame;
}
Ball3_mc.onEnterFrame = function(){
        this._x = 50 + Math.easeInOut(currentFrame/50, 1, Math.ezCirc) * 450;
        if(currentFrame > 50) delete this.onEnterFrame;
}
Ball4_mc.onEnterFrame = function(){
        this._x = 50 + Math.easeInOut(currentFrame/50, 2, Math.ezExpo) * 450;
        if(currentFrame > 50) delete this.onEnterFrame;
}
//____________________________________________





As you can see, changing the equations used to ease our ball can produce a fairly wide variety of results, ranging from the subtle to the extreme. If you'd like to check out a few more alternate easing equations I suggest you visit Robert Penner's site and examine some of his excellent easing equations.



The next portion of this tutorial will demonstrate a bunch of different ways we can apply our easing functions to achieve an even wider variety of effects.