This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.
Easing is a way of moving from one location to another, so that the speed of the object that moves along its track varies. This tutorial will deal with a specific type of easing called ‘Easing Out’; easing in a way so that the object’s speed decreases as it nears its destination. The complement of Easing Out is Easing In, and since they are both similar, I will mention Easing In only in passing towards the end of the tutorial.
Consider the following two examples to get a good grasp
of what the difference is between the two. Both
represent an object moving from the
left towards a destination on the right, but in two
different ways. The first one uses no easing at all ( a
constant speed ) to move to its destination, the second
uses ‘Easing Out’ to move to its destination. From now
on I will refer to ‘Easing Out’ as simply ‘easing’, for
the sake of consistency and readability.
The above example does not use any easing. Notice how the square's speed stays constant throughout the movement.
On the other hand, the above square
contains a slight easing. You should see the square
start to decelerate as it nears its destination.
So, easing as we’ll discuss it here is the way of moving
where an object slows down as it nears its goal. The key
to implementing this in Flash might be simpler than you
thought. What happens is basically you take the distance
between the object and its destination, divide it by a
number greater than 1, and you now have a distance that
is smaller. We then move our object to be at the newly
calculated distance from its destination, and repeat
this reduction as long as necessary.
Why does this make it ease? Well, since we’re dividing,
the greater the distance is between the object and its
destination, the greater the difference in calculated
distance will be in absolute terms. Put otherwise: the
closer the object gets to its goal, the smaller the
distance to the goal is. The smaller the distance to the
goal, the smaller the distance will be that we
calculate. The smaller the distance is that we
calculate, the less we move the object moves towards its
goal. Thus we have easing movement.
That might sound a bit confusing. Consider the following
example: we have an object that is currently at position
0, and we want to ease it to position 120. We must first
pick a number to divide each distance by, as this will
determine the speed of our easing motion. Let’s pick 2.
We can now follow these steps:
Take the distance between the object’s current position and its destination
Divide this distance by 2
Move the object towards its destination, so that it is the distance we calculated in step 2 away from it.
Repeat Step 1
Indeed, this is a loop, every iteration through it updating the object’s position. To clarify how it works, here’s a visual representation. The line on the left indicates the object’s starting position (0), and the line on the right indicates the object’s destination (120). The orange line represents the object’s new position, calculated by dividing the distance between current position and destination by 2.





Considering that you can go on and on, always dividing the distance by 2 (don’t worry about ending the loop yet), we get the following movement pattern:

Now that you have an understanding of how to think about easing out effects, let's delve into how easing can be implemented in Flash.
From the previous section, we have thought out how our easing works. Now, how can we apply this easing method in Flash? This page will start you on your path to finding out!
In any case, our function will have to use some sort of loop construction, so that we can have it follow the above steps inside it to create our easing movement. For and While loops are out of question here, as these would loop way too fast, making the movement practically invisible. The human eye cannot interpret a series of images as fast as a computer can execute for and while loops.
Luckily, Flash provides us with the onEnterFrame handler, which is called every time right before Flash draws a frame of the movie to the screen. The speed at which Flash does that is set by the movie’s Frames Per Second ( FPS ) value. An FPS value of 24 means that Flash will draw a frame to the screen 24 times every second. This value is also the minimum FPS needed for the human eye to consider a sequence of images as an animation. I personally tend to use an FPS setting of 40: more than sufficiently fast, and not too resource-consuming.
By relying on the movie’s FPS, we have an excellent loop to use. Here is some example code that implements the very first version of our easing function that will ease MovieClips along the stage following the x axis. In Flash, we will most commonly be easing MovieClips, as these are the most generic stage objects in Flash. Other stage objects such as TextFields or Buttons can also easily be eased using our final version of the function, but that’s an issue for when we get there. Furthermore, MovieClips directly implement the onEnterFrame handler which other stage objects don’t, so that we do not have to worry about using helper MovieClips and the likes just yet.
var speed:Number = 2;
ease = function( what:MovieClip , to:Number ){
what.onEnterFrame = function(){
var distance:Number = to - this._x;
var newDistance:Number = distance / speed;
this._x = to - newDistance;
}
}
The first line sets the speed at which we will be easing. This is not really a speed at which the MovieClip advances (because that will decrease as it nears its destination), it is instead the value we will use to divide each distance by. This uniquely defines the speed of the easing.
Important
The value of speed must always be strictly greater than 1! If not, you will be moving your object away from it’s goal rather than towards it, or not moving it at all.
Check out the following example:
What’s important here is the ease function. It takes two arguments: the MovieClip to ease, and the x position to ease it to. Inside that function, we can see that the onEnterFrame event handler is being set for the MovieClip we’re easing. Every frame, we take the distance between the destination and the current position. We then divide that distance by 2; I assigned this value to the variable speed earlier. We then position the MovieClip to be newDistance away from its goal, thus we have successfully implemented our easing movement.
In the previous section, we reviewed what we want our easing function to do in three statements. We can write those 3 statements inside the onEnterFrame handler’s body as a single statement like this:
var speed:Number = 2;
ease = function( what:MovieClip , to:Number ){
what.onEnterFrame = function(){
this._x = to – ( to – this._x ) / speed;
}
}
And there we go ! We have achieved a function that will
easy any MovieClip to any point on the x axis, in just
these 6 lines of ActionScript ! Excellent, but we have
been ignoring something up till now: this onEnterFrame
handler has not been told to ever stop, which means it
will still be calculating even long after the
destination has been ‘reached’.
Theoretically, it can never reach its destination, much
like 0.9999999…. will never reach 1. But, computers have
limitations in calculating floating point numbers, and
therefore so does Flash, and so do screens. At a certain
point you’ll end up calculating these insanely small
numbers, and moving the MovieClip on the stage by that
distance won’t have any effect, because those amounts
won’t even add up to a hundredth of an actual pixel to
move.
So, we have to build in some kind of a check to see when
the MovieClip has very closely neared its destination,
and then remove the onEnterFrame handler. That way, the
onEnterFrame handler won’t keep calculating values that
have no effect anyway. This is important in big projects
where CPU load is an issue. Trust me, you do not want an
onEnterFrame stalling in the background for every
MovieClip you’ve ever eased around.
Therein lies a problem: because the MovieClip will never
actually reach its destination, it is pointless to check
if it has. What we could do is set some kind of ‘null
distance’ that will determine how far the MovieClip
needs to be away from its destination to be considered
‘there’. This method works well if you stick to a
certain speed and ease all MovieClips using that speed,
but unfortunately it does not make for a good general
solution. This is because the null distance depends on
the speed of the easing. The slower the speed, the
slower the object will be moving towards its
destination, and the finer the dividing of the
distances. The finer the dividing of the distances, the
more MovieClip positioning limitations will take effect.
This makes the null distance method fairly unreliable.
A better solution is to keep track of the previous
positions of the MovieClip, and compare them to
each other. There will always be a certain point where
the difference between the distances will be so small
that Flash won’t bother to update the MovieClip to that
position because moving a MovieClip over such a small
distance is either meaningless or simply impossible.
When that happens, two consequent positions will be the
same, indicating that Flash has reached its limitation
of MovieClip positioning and that further calculations
will have no effect anymore. This is when we want our
loop to end.
Fortunately, performing this check is easy. All we need
is an extra variable that holds the previous position.
When we move the MovieClip to its new position, we check
if this new position is the same as the last one. If it
is, then we have reached our limit and we can safely
kill the loop because further calculations are pointless
as they will all result in the same position. And to
ensure maximum positioning accuracy, we can set our
MovieClip to its exact destination once this happens.
Just to be sure.
With that in mind, we can redefine our easing function
like this:
var speed:Number = 2;
ease = function( what:MovieClip , to:Number ){
var previousPosition:Number = what._x;
what.onEnterFrame = function(){
this._x = to – ( to – this._x ) / speed;
if( this._x == previousPosition ){
this._x = to;
delete this.onEnterFrame;
}
previousPosition = this._x;
}
}
We now have our easing function. But a function is only a function, and when you’re working on a project with a rather large hierarchy of MovieClips, you’ll find it annoying to always have to create a huge path to that one function somewhere on the main timeline to call it from way down in your MovieClip hierarchy.
Luckily, Flash provides us with the MovieClip.prototype
object to easily solve this issue. I will not discuss the
ins and outs of what prototype objects are and how they
work: for an excellent and all-in explanation anything
you’ll ever need to know about AS 1.0 OOP, please read this
tutorial by resident Flash guru Senocular. It’s a
long read, but it’s your road to Flash enlightenment.
By defining this function in the MovieClip.prototype
object, every MovieClip anywhere will be able to call
this method as if it were their own. The prototype
function looks like this:
MovieClip.prototype.ease = function( to:Number , speed:Number ){
var previousPosition:Number = this._x;
if( isNaN( speed ) || Number(speed) !== speed || speed <= 1 ) speed = 1.2;
this.onEnterFrame = function(){
this._x = to – ( to – this._x ) / speed;
if( this._x == previousPosition ){
this._x = to;
delete this.onEnterFrame;
}
previousPosition = this._x;
}
}
Notice that we have made a few additional changes here.
The speed value can now be passed along as an argument
to the function, allowing for every MovieClip to be
eased at an individual speed. If the speed value is in
any way incorrect, it will default to 1.2.
Now that we have defined our function as a prototype
method, we can apply it to any MovieClip we want.
Whereas previously you would call the easing function
like this:
ease(myMovieClip,600);
We can now call it like this:
myMovieClip.ease(600, 1.2);
Which, I’m sure you’ll agree, is handier to work with, especially when we’ll be adding functionality later on.
We can now look further into optimizing this method of
easing. For example, what if the MovieClip is already at
the position it was called to ease to ? Simple: the
onEnterFrame loop will be entered, its next position
will be calculated, the difference in position will be
0, so that the next position will equal its starting
position. Therefore the new position will immediately
equal its previous (starting) position, and the loop
will immediately exit.
Even though this will work just fine, this is not good
programming practice. When you move a MovieClip to the
position it’s already at, you haven’t done anything. So
it also would make sense for our function not to do
anything either. An easy if check will make sure of
that:
MovieClip.prototype.ease = function( to:Number , speed:Number ){
if( what._x != to ){
var previousPosition:Number = this._x;
if( isNaN( speed ) || Number(speed) !== speed || speed <= 1 ) speed = 1.2;
this.onEnterFrame = function(){
this._x = to – ( to – this._x ) / speed;
if( this._x == previousPosition ){
this._x = to;
delete this.onEnterFrame;
}
previousPosition = this._x;
}
} else {
// do nothing
}
}
We now have generic easing function that can be applied
to any MovieClip anywhere in the movie using an
individual speed setting, and cleans up after itself.
Looking even better!
The above animation shows all of the code I have explained in action.
So far we have focused on implementing easing and making the implementation more portable (see previous section), but there are some edge cases that we will need to address before you can use this effect without running into any issues.
Up till now, our method has always been using the onEnterFrame handler of the MovieClip it was easing. This is an issue when we want to ease a MovieClip that already has an onEnterFrame handler set to perform some other task. We can’t just assume that it’s ok for us to overwrite any MovieClip’s onEnterFrame handler!

[ the MovieClip’s onEnterFrame handler directly sets its own _x property – not good ! ]
Considering that every MovieClip instance listens to the
onEnterFrame event, the solution to this problem is
obvious: we’ll just use another MovieClip’s onEnterFrame
handler ! But which MovieClip ? It has to be one of
which be can be sure it has no onEnterFrame handler
already in use. The only way we can be sure about that,
is by spawning and using an auxiliary MovieClip. Because
our auxiliary MovieClip has just been created, we are
sure that it does not have an onEnterFrame handler
already in use.
So where do we spawn this auxiliary MovieClip ? Since
every MovieClip must be able to ease separately from any
other, we will create it inside the MovieClip we will be
easing. This also enables for easy targeting: our
auxiliary MovieClip will only need to target its parent
MovieClip to get a reference to the MovieClip it will be
easing around.

[ A better way of doing it: delegating the onEnterFrame to an auxiliary child MovieClip ]
Spawning MovieClips through ActionScript is done using
the createEmptyMovieClip function. The new MovieClip will be
created inside the MovieClip that called the method,
making the MovieClip that called the method the parent
of the newly created MovieClip. When creating it, you
must specify an instance name and a depth for the
MovieClip. The choice of these two values is important,
as they both have to be unique for each easing method.
Right now we’re seeing a method of easing along the X
axis, but we will also see methods for easing a
MovieClip’s width, height, y position, scale, etc.
That’s why we will now rename our easing function to
easeX, to differ between any additional future easing
methods. Because a MovieClip should be able to ease more
than 1 of these properties at the same time, we must
make sure that all the easing methods use different
auxiliary MovieClips that take care of the separate
easing loops. And to ensure they are all different, we
must ensure that they all have both consistently unique
instance names and consistently unique depths.
MovieClip.prototype.easeX = function( to:Number , speed:Number ){
if( what._x != to ){
var _this:MovieClip = this;
var aux:MovieClip = this.createEmptyMovieClip( “aux_easeX” , 1337 );
var previousPosition:Number = this._x;
if( isNaN( speed ) || Number(speed) !== speed || speed <= 1 ) speed = 1.2;
aux.onEnterFrame = function(){
this.x = to – ( to - this.x ) / speed;
if( this.x == previousPosition ){
this.x = to;
this.removeMovieClip();
}
previousPosition = this.x;
}
} else {
// do nothing
}
}
Notice that we are now no longer just removing the
MovieClip’s onEnterFrame, but rather the entire
auxiliary MovieClip. This because when the easing
movement has ended, this extra MovieClip has lost its
purpose and should be deleted. For easy code adjustment
within the loop body, we have saved a reference to the
parent MovieClip being eased as _this, so that we need
only replace the this by _this in order to target the
MovieClip we’re easing instead of the auxiliary
MovieClip.
So now, we can ease MovieClips around just like before,
but this time keeping their onEnterFrame handler intact.
We are almost done with this tutorial. In the previous section, you learned how to avoid overwriting a movie's onEnterFrame handler. In this page you will learn one more trick, and then I will conclude this tutorial with a collection of source files used in the various animations you have seen.
When applying this easing method in various projects,
you will find that you will often want to call another
function after the easing has ended. For example, you
may want to slide open a panel by moving it from one
side to the either, and when it has, load your content
into it. You don’t want your content to already start
loading before your MovieClip is in place.
To solve this problem, we can use what I like to call
function chaining. More accurately I’d call it function
call chaining, but the former sounds better. The idea is
to pass along a function to the easing method that is to
be called when the easing has completed. That way, you
can say: ease this MovieClip to this position at this
speed, and when it’s done, call this function.
The way we’ll be doing this is by using the
Function.apply method. The syntax is as follows:
myFunction.apply(thisObject,argumentsObject);
This will call the function myFunction as a method of thisObject, using the set of parameters as indicated by the argumentsObject array. Notice that this allows for a method to be applied as a method of another object rather than the object that defined it. Consider the following example:
var objectA:Object = new Object();
var objectB:Object = new Object();
objectA.myProperty = "property of A!";
objectB.myProperty = "property of B!";
objectA.theProperty = function(){
trace( this.myProperty );
}
objectA.theProperty.apply(objectB,[]);
This will apply the method theProperty as
defined by objectA to objectB, even though it is was defined
in objectA. This allows for great flexibility in calling
functions.
To implement this, the code looks like
this:
MovieClip.prototype.easeX = function( to:Number , speed:Number , endF:Function , endO:Object , endP:Array ){
if( what._x != to ){
var _this:MovieClip = this;
var aux:MovieClip = this.createEmptyMovieClip( "aux_easeX" , 1337 );
var previousPosition:Number = this._x;
if( isNaN( speed ) || Number(speed) !== speed || speed <= 1 ) speed = 1.2;
aux.onEnterFrame = function(){
_this._x = to - ( to - _this._x ) / speed;
if( _this._x == previousPosition ){
_this._x = to;
this.removeMovieClip();
if( endF ) endF.apply( endO , endP );
}
previousPosition = _this._x;
}
} else {
if( endF ) endF.apply( endO , endP );
}
}
We can now optionally pass three more
arguments to our easing method: endF ( for endFunction )
refers to a function that will be applied once the easing is
complete. Consistently with endF, we pass along endO ( for
endObject ) and endP ( for endParameters ) which are
respectively the object that endF will be applied to and the
set of parameters that will be sent along with the call.
Notice that our else clause has now become useful: if our
object is already at its destination, we still want our
ending function to be called. Before, that else clause was
just doing nothing.
We can now chain functions calls
one after the other; for example, we can have a MovieClip
ease to a certain position and then back at a different
speed:
var startX:Number = myMovieClip._x;
var endX:Number = startX + 500;
myMovieClip.easeX(endX, 1.2, myMovieClip.easeX, myMovieClip, [startX, 1.4]);
Again, notice the flexibility of the Function.apply method: the function we are calling is myMovieClip.easeX, but that doesn’t necessarily mean we also want to apply it to myMovieClip, we could also have applied it to any other MovieClip to ease that one instead of myMovieClip. And because myMovieClip.ease isn’t defined in myMovieClip but in its prototype object, all the following are equivalent:
myMovieClip.easeX(endX, 1.2, myMovieClip.easeX, myMovieClip, [startX, 1.2]);
myMovieClip.easeX(endX, 1.2, MovieClip.prototype.easeX, myMovieClip, [startX, 1.2]);
myMovieClip.easeX(endX, 1.2, myMovieClip.__proto__.easeX, myMovieClip, [startX, 1.2]);
myMovieClip.easeX(endX, 1.2, myMovieClip.createEmptyMovieClip("randomMC", myMovieClip.getNextHighestDepth()).easeX, myMovieClip, [startX, 1.2]);
myMovieClip.easeX(endX, 1.2, _root.easeX, myMovieClip, [startX, 1.2]);
Again, for a closer understanding why this
is, please read
Senocular's AS1 OOP tutorial.
We can even
have it continuously ease it back and forth:
The code I used the call the easeX prototype function is the following:
var startX:Number = myMovieClip._x;
var endX:Number = startX+500;
chain = function () {
myMovieClip.easeX(endX, 1.2, myMovieClip.easeX, myMovieClip, [startX, 1.4, chain, null, []]);
};
chain();
This to illustrate the power of function chaining. In fact, I don’t think I have ever been working on a project where I haven’t used this easing method. It’s just everywhere, and the function chaining makes it easy to control the exact behavior of your application, with no guessing work involved.
As I have mentioned earlier, this method of easing can
be used to ease all kinds of properties, including but
not limited to the _y, _xscale and _yscale, _width,
_height, and even _alpha properties. And this is where
the power of the function chaining really comes into
play: you can control exactly how and when you want your
ActionScripted easing animations to take place.
|
|
Download proto.as |
In the file proto.as you will find easing methods for the most common properties such as _x, _y, _width, _height and the likes, logically called easeX, easeY, easeWidth, easeHeight, and so on. You can easily use these in your movies by placing proto.as in the same folder as your .fla is in, and then include them:
#include "proto.as"
This will import the prototype method definitions into
your movie, allowing you to easily use them without
having them clutter up your ActionScript panel. Have a
look at the example file example7_proto.fla in the
following zip file to see them
all in action.
This concludes this tutorial. If you have
any further questions or if you notice something you think
is wrong, please don’t hesitate to let us know on the
forums.
Peace out,
![]() |
Voetsjoeba voetsjoeba.com |
Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence, ads, and algorithm-driven doodads. A huge thank you to all of you who buy kirupa's books, became a paid subscriber, watch the videos, and/or interact on the forums.
Your support keeps this site going! 😇
:: Copyright KIRUPA 2026 //--