Saturday, March 07, 2009

Creating a preloader in ActionScript 3.0

One of the major advantages of Flash over a standard html/css page is the ability to add a preloading animation to the beginning of the swf file to keep your audience entertained while they wait for the movie to load. There are many different strategies that you can adopt when building a preloader. Some people will create a custom document class and use that for all of their new flash documents, while others might create a quick animation in the first few frames of there movie and then use script to loop them until the movie loads. The approach taken here is to add code to the first frame of the flash file the creates a preloading animation and once it detects that the movie has completed loading it moves on to the next frame.

This is the code that is placed in the first frame of the Actions Layer:


stop();

this.loaderInfo.addEventListener(Event.COMPLETE,movieLoaded);
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS,onProgress);

var myTextField:TextField = new TextField;
addChild(myTextField);
myTextField.width = 200;

myTextField.height = 20;

myTextField.x = stage.stageWidth/2;
myTextField.y = stage.stageHeight/2;

function onProgress(myEvent:ProgressEvent) {
    myTextField.text = "Your download is " + Math.round(myEvent.bytesLoaded/myEvent.bytesTotal*100) + "% Complete"; 
}

function movieLoaded(myEvent:Event) {
    removeChild(myTextField);
    gotoAndStop(2);
}


Lets take a look at what each part of the code actually does:

Step 1: Stop the Playhead
The first line is very simple it stops the playhead from moving onto the second keyframe.
stop();

Step 2: Create the Event Listeners
The next block of code is what creates the two event listeners that the preloader needs to function. When you are dealing with events and functions triggered by events there are two parts of the equation. The event listener waits for an event to occur and then calls an event handler. If you aren't familiar with them, event listeners are used to wait or listen for a specific event (that event can be user triggered such as a click event or as it is here by a loading event) and then triggers a function (the event handler). Here are two listeners, the first is declared as a generic event and is triggered by the complete state of the movie clip loading while the second is a progress event that is triggered by the progress of the loading event.

this.loaderInfo.addEventListener(Event.COMPLETE, movieLoaded);
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);


Understanding the eventListener:
The "this" keyword is used to target the main movie. The event listener can't be attached directly to the movie so you have to attach it to the loaderInfo property of the swf. The listener waits for the complete event of the movie clip before it fires off the function named movieLoaded (this function will be declared later in the code).

this.loaderInfo.addEventListener(Event.COMPLETE, movieLoaded);

Step 3: Create the display object
For a preloader to be of any use you have to create some type of visual representation of the act of loading. Here in this example I will use a text field that updates to show the loading progress. For greater control I am going to create this text field dynamically with the next block of code. The first line is an object request and uses the var keyword to declare a new object named "myTextField" the phrase TextField after the colon sets the data type of this new object. Data typing is important because it declares waht type of object this is an therefore what type of information it holds. The object is instantiated by the text on the right side of the equal sign using the new keyword and again stating the data type. The addChild() command is used to add the new text field (myTextField) to the display stack. So the first line creates the new text fied object and the second line makes it show up on the stage.  The third line begins the code that will control the position of the object named myTextField. For the x and y position of the text field are set to use the stage width and height instead of a static number. This is helpful because if I change the size of the stage the text field wil still be in teh same relative position.
var myTextField:TextField = new TextField;

addChild(myTextField);

myTextField.width = 200;
myTextField.height = 20;
myTextField.x = stage.stageWidth/2;
myTextField.y = stage.stageHeight/2;

Step 4: Create the onProgress event handler
Event handlers are functions that are triggered by event listeners. They are like your cellphone, when it recieves a call it rings, this is how the handler works when it is triggered by the listener it runs the commands located between the braces. The first event handler that I create here is the onProgress function. Like all functions it begins with the function keyword and then the name of the new function. Inside of the parentheses of the new function the event that triggers it is passed from the listener to the handler. This is how the functions knows what should trigger it, without this line the function would fail. The work myEvent is used as the name of the event inside of this function and is completely arbitrary while the type of event is taken from the listener that triggers this function. Think of it as an internal variable, that exists only inside this function and only exists for the duration of the event. The result of the function is that the text property of the myTextField object is set to display everything on the right side of the equal sign. The text (called a string) is placed inside of quotes and a mathematical formula that displays the amount of the movie that has downloaded as a number (the .round makes sure the number is rounded off) is added to it using the plus signs.

function onProgress(myEvent:ProgressEvent):void {
    myTextField.text = "Your download is " + Math.round(myEvent.bytesLoaded/myEvent.bytesTotal*100) + "% Complete"; 

}

Step 5: Create the movieLoaded event handler
The second function created here is triggered by the event handler tied to the completion of the movies loading event. It does two thing, the first is to remove the myTextField object using the removeChild command and the second is to move the playhead to the second frame of the swf file. The target frame could easily be changed by replacing the two in the parenthesis with the number of your destination frame.
function movieLoaded(myEvent:Event) {

    removeChild(myTextField);

    gotoAndStop(2);

}


Special Thanks to my good friend Fred Gerantabee. Check out his blog at: http://flashthismofo.blogspot.com/

Technorati Tags: , , , ,