by
Voetsjoeba | 9
December 2006
We are almost done with this tutorial. In the
previous page, 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.
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,
|