Making a Flash website menu with a preloader for external sections – part 4 of 4
This is the fourth part of the lesson on creating a Flash menu with loader for external content.
The ActionScript code behind the menu preloader system explained
The first line of ActionScript,
menu_mc.stop();
Stops the menu_mc
movie clip from playing. Every timeline animation in Flash plays automatically, so you have to stop it via ActionScript if you don’t wish for it to start moving. The animation inside the menu_mc
are the white stripes that you made earlier.
Next, the section
variable is defined, which will store the name of the section that must appear once the user has clicked on the appropriate button. This is a text value and text values are called Strings in ActionScript, as in most programming languages. You are just defining the variable here, values will be added later.
var section:String = new String();
Four more variables are defined next:
var menu:MovieClip = menu_mc;
var startSection:MovieClip = content_mc.homecontent_mc;
var externalSections:MovieClip = content_mc.placeholder_mc;
var percentageDisplay:MovieClip = menu_mc.loadinfo_mc;
All these variables are of the MovieClip
type. You are not creating new movie clip instances here, you are merely making shorthand names for existing movie clips that you have created earlier. This is just to make your life easier — to reduce the amount of typing that has to be done.
Look at this example: let’s say that you need to reference the menu_mc
movie clip from within the homecontent_mc
movie clip. In that case, you would have to reference it like this:
this._parent._parent.menu_mc
That is a pretty long reference, although valid and completely correct. You would have to write it like that, because the homecontent_mc
is itself inside content_mc
, its parent movie clip (_parent
), which is in turn on the main timeline (_parent
), on which the menu_mc
resides. And this reference path changes for every movie clip.
So, instead of having to figure out the path each time (and pay attention that it is the correct one), it is much simpler to store the reference to each movie clip that you need inside a variable, like this:
var startSection:MovieClip = content_mc.homecontent_mc;
And that’s just what the four variables mentioned above serve for: easy referencing of movie clips. Any time that you mention the variable menu
, for example, inside your code, Flash will instantly know that you are referring to the movie clip menu_mc
which is situated on the main timeline. Cool!
The next line of code,
percentageDisplay._visible = false;
Serves to hide the movie clip with the dynamic text field on a white transparent background inside it. This is reasonable: why should the preloader be visible if there is no loading in progress? And there actually is no loading process at the beginning, until the moment a button is pressed by the user.
The percentageDisplay
variable is a reference to the loadinfo_mc
movie clip which was defined a few lines of code before. By setting its _visible
property to false
, you are effectively hiding it from the view.
Using a MovieClipLoader object with a listener to preload external Flash content
The preloading system shown in this lesson uses a MovieClipLoader object for external content preloading (in fact, to be exact, this is an ActionScript class, but I won’t delve into that here, for the sake of brevity and simplicity. I will leave that for another tutorial). This object is very useful, because it has built-in methods and properties for preloading that are great, and it can be used to load external SWF files, as well as JPEG, GIF and PNG type of images. It can even load progressive JPEGs and animated GIFs.
So, the first line of this section of code creates a new MovieClipLoader object and stores it in a variable that I chose to call loader
.
var loader:MovieClipLoader = new MovieClipLoader();
Next, a listener object is associated with the loader
MovieClipLoader. This is done by first writing the instance name of the MovieClipLoader object, which is loader
in this case, followed by a dot (.
) and the addListener
method. Between the parenthesis of this method is the name of the listener object.
A listener object can be a completely new, custom object, created specifically to be a listener, or any existing movie clip. Since the main timeline (the root timeline) in Flash is also considered to be a movie clip, I chose to use it as the listener. The main timeline is referenced here by the ActionScript keyword this
. This keyword points to the timeline or movie clip it is placed upon. Since the ActionScript code in this lesson resides on the main timeline, it refers to it directly.
loader.addListener(this);
Let me explain you now in more detail how the MovieClipLoader works together with a listener:
First, you need to have an empty movie clip into which the external content will be loaded. You already did that, when you created the empty movie clip back in step 78 of this tutorial (you called it placeholder_mc
, remember).
Then, an instance of the MovieClipLoader object is created (see above).
Next, a listener object is either created from scratch or an existing object (the main timeline in this example) is used as a listener. The listener will listen to what MovieClipLoader does. You can think of it as a small radar that watches the MovieClipLoader object, which broadcasts events to it (it tells the listener that things are happening).
Once things start happening, for example, the MovieClipLoader begins to load external content, and fetches the amount of it that has been loaded so far, etc, the listener will notice this, since it is listening to it. And when it notices these events, it will react by executing the appropriate functions.
Important: for the listener to be able to react properly, these functions must be defined before you tell the MovieClipLoader object to start loading external files. There are two functions that are being used in this lesson’s preloader: onLoadInit
and onLoadProgress
. Let me clarify them for you, one at a time:
The onLoadInit
function is invoked (called) once the external file has been completely downloaded onto the user’s computer from the Web and is ready to be shown, manipulated, etc.
function onLoadInit(externalSections:MovieClip) {
menu.stop();
percentageDisplay._visible = false;
}
The parameter between the onLoadInit
function’s parenthesis is a reference to the movie clip into which the external content is being loaded. This is the empty movie clip that is referenced by the externalSections
variable in this example.
In this example, I made the following things happen once the external content has been completely loaded: the stripes inside the menu will stop moving:
menu.stop();
…and the movie clip with the dynamic text that shows the percentage information during the loading process is being made invisible:
percentageDisplay._visible = false;
Basically, all the things that are visible during the loading process are hidden once the download is complete.
Both event handler functions used here that are associated with the listener, onLoadInit
and onLoadProgress
are not written with the name of the listener preceding them, and they should. Why? Simply because they are placed on the main timeline, which is the listener in this case.
Had that not been the case, for example, if the menu_mc movie clip were the listener, you would have to write them like this:
menu_mc.onLoadInit… etc
menu_mc.onLoadProgress… etc
But, since the root timeline is assigned to be the listener, you just write the keyword function
and everything’s just fine. You don’t even have to use the keyword this
.
Next, the onLoadProgress
function is used to monitor the loading process. Every time a piece of external file has been downloaded to the user’s computer, the loader
MovieClipLoader object tells this to the listener, which reacts by calling the onLoadProgress
function.
function onLoadProgress(externalSections:MovieClip, loaded:Number, total:Number) {
if (section != "home") {
externalSections._visible = true;
startSection._visible = false;
percentageDisplay._visible = true;
menu.play();
var percent:Number = Math.floor(loaded/total*100);
percentageDisplay.infodisplay_txt.text = "LOADING: "+percent+"%";
}
}
The onLoadProgress
function accepts three parameters:
The first one, externalSections
, just like in the previous function, is a reference to the empty movie clip into which the external content gets loaded.
The second one, loaded
, is the number of bytes that have been downloaded to the user’s computer so far. This value gets updated each time a new piece of data gets downloaded — that’s why this function is great for monitoring the progress of a download. This happens automatically, meaning that there is no need for you to tell Flash to look it up or explain to it what is the loaded
parameter. It knows immediately that the second parameter refers to the amount of bytes loaded so far. Also, you can call it as you like: I picked loaded because it seems nice. You can also call it loadedbytes
, downloadeddata
or anything else that seems right to you.
The third one, total
, looks at the total size of the external file that is being loaded, the value of which is expressed in bytes, just like it was for the previous parameter.
And now, let me show you how this function makes the preloader actually work. Inside the onLoadProgress
function there is an if
conditional statement. All the code is included inside it. This means that it will get executed only and only if the condition turns out to be true. Let’s see this condition. It says that:
if (section != "home")
Which, translated into English means if the section does NOT equal “home” the condition will be true. This is made with the use of the inequality operator (!=
), which compares the two values to see if they do not match.
In this example, this means that only when the value of the variable section
does not equal “home”, the code between the conditional statement’s curly braces will be executed. I have made this on purpose, to be able to start the preloader only when a button which triggers the loading of an external SWF file has been clicked. The section
variable has been defined at the beginning of the ActionScript code, while its value is set only when a button has been clicked. Remember that the onLoadProgress
function has to be defined now, so that Flash can know what to do when ordered to load an external file via the MovieClipLoader object.
So, the preloader won’t start if the Home button has been clicked, because the content for the “home” section is already incorporated in the main movie — it is not stored in an external SWF file, like the other sections are.
And when a button other than “home” has been clicked, the code inside the if
statement gets executed:
externalSections._visible = true;
startSection._visible = false;
percentageDisplay._visible = true;
menu.play();
var percent:Number = Math.floor(loaded/total*100);
percentageDisplay.infodisplay_txt.text = "LOADING: "+percent+"%";
The first line makes visible the movie clip which holds the externally loaded SWF (externalSections._visible = true;
). You have to make it visible here, because it was hidden initially. Next, the “home” section is made invisible: startSection._visible = false
. These changes have to be made, so that the initial content (”home”) does not visually interfere with the other sections’ content.
The third line makes the preloader movie clip visible (the one with the text field inside it): percentageDisplay._visible = true
.
The fourth one gets the stripes moving, to further add to the loading effect: menu.play();
.
And now you have two lines with some simple mathematical calculations that enable you to show the amount of the external SWF loaded so far, expressed as a percentage:
var percent:Number = Math.floor(loaded/total*100);
percentageDisplay.infodisplay_txt.text = "LOADING: "+percent+"%";
The value of the percent
variable is calculated by Flash like this: the number of bytes loaded so far are divided by the total number of bytes the file has and then multiplied by 100 (loaded/total*100
). The result is then rounded with the Math.floor
method, which rounds the resulting number in the parenthesis to the lower whole number. For example, if the number is either, let’s say, 43.1, 43.8 or 43.5, it will always be rounded to 43. This is used to display a neat whole number in the text field, without any trailing digits.
And then you order Flash (see second line of code above) to display that number in the infodisplay_txt
text field, along with the word “LOADING” and the percentage sign (%). Simple, isn’t it? No rocket science :-).
And now you’ll see how this process gets started, once the user has clicked a menu button.
The ActionScript behind the buttons’ functionality
All the buttons in this project are set up so that they react to the onPress
event. This event happens when a user clicks on a button — immediately when the mouse button is pressed, without having to be released. And so, each button has its onPress
event handler function set up that is executed as soon as the click happens: the code inside the function (the one included between its curly braces) is the one being run.
I will first explain to you how the “Home” button works, since this particular button has a different functionality then all the other menu buttons. The main difference being that the “Home” button doesn’t start the loading of external content.
menu.home_btn.onPress = function() {
menu.stop();
percentageDisplay._visible = false;
section = "home";
startSection._visible = true;
externalSections._visible = false;
};
The first line inside the function stops the menu animation (the white stripes): menu.stop()
. This is done so that they stop moving if the “Home” button was pressed when some external content was loading. This means the case in which the user has pressed any other button and the external content started to load, and the preloader/stripes animation kicked in. So you have to stop it once the “Home” button was clicked.
After that, the textual preloader has to be made invisible:
percentageDisplay._visible = false;
And the section
variable’s value is set to “home”:
section = "home";
The last two lines of code make visible the movie clip which holds the “home” section’s content and invisible the one which serves as the placeholder for the external content:
startSection._visible = true;
externalSections._visible = false;
All the remaining buttons have the exact same functionality, only with a different parameter that is set up inside them. Let’s have a look at the “services” menu button, for example.
menu.services_btn.onPress = function() {
section = "services.swf";
loader.loadClip(section, externalSections);
};
The first line inside the button’s onPress
event handler function defines the value of the section
variable:
section = "services.swf";
This value (services.swf in this case) has a dual purpose: it is the name of the external SWF that will be loaded, and it also sees that the loading actually starts, because, if you remember, the loading process will start only if the section does not equal “home”:
if (section != "home")
This was defined in the onLoadProgress
function before.
And now, the actual loading is triggered by calling the loadClip
method of the loader
MovieClipLoader object:
loader.loadClip(section, externalSections);
The loadClip method can be used to load external content, namely these kinds of files: SWF, JPG (both non-progressive and progressive, as of Flash Player 8), GIF (ordinary and animated ones) and PNG.
The first parameter inside the loadClip
method’s parenthesis is the name of the external file that has to be loaded. Here, it is a variable: section
. Its value was defined a moment ago, in the previous line of ActionScript code. When you are using a variable, you write the variable’s name, without the quotation marks. If you are referring to a file name directly, you must use the quotation marks, for example:
loader.loadClip("mycontent.swf", externalSections);
This can also be a path, for example:
loader.loadClip("myflashfiles/mycontent.swf", externalSections);
I have avoided storing the sections in a separate folder and thus didn’t need to use a path to the sections’ files, just for the sake of simplicity. However, there is an important thing that you should be aware of:
Concerning the loading of external data with the loadClip
method, the Flash help (the one that shows up when you press F1 in Flash) states that “A relative path must be relative to the SWF file…” I found out that this is NOT the case. The path to the external file must be relative to the HTML file inside which your main SWF file is embedded!
The second parameter is the empty movie clip into which the external content will load, which is externalSections
in this example (a reference to the placeholder_mc
movie clip).
And as soon as Flash reads this last line of code, the MovieClipLoader object and the listener spring to life, making the preloader work. All the other buttons work exactly the same, the only difference being the value of the section
variable.
There remains one thing to be done: create the preloader for the main movie.
Adding a scene for the main preloader
91 Back to your Flash document, select Window > Other Panels > Scene.
92 The panel for managing the scenes in your document will appear. Double-click on the Scene 1 name and change it to main. Hit Enter to confirm that.
93 Click the Add scene button (the plus icon) at the bottom of the Scene panel.
94 Call the new scene preloader. Next, click on it and drag it above the main scene.
This is done so that the scene with the main preloader will appear first. Different scenes in Flash are all part of the same timeline, which plays out sequentially, with the scene that is on top of all the other ones in the Scene panel appearing first.
Creating the main Flash website preloader
95 Create the same big blue rectangle which you have drawn at the beginning of this tutorial. Its dimensions are 480 by 52 pixels. You can copy the one from the main scene if you want and place it here, in the preloader scene.
96 Go to the Library (Window > Library). Find the loading info display movie clip. Click on it and drag out an instance of it onto the scene. You can place it right over the blue rectangle — they won’t interfere with one another, since the rectangle is a simple drawn shape and the other one a movie clip symbol.
97 Select the loading info display movie clip and go to the Property inspector. Assign it the Instance name mainpreloader_mc.
You can leave the instance name of the dynamic text field inside it as it already is, infodisplay_txt.
98 Lock the current layer and call it preloader. Make a new layer above it and call it actions. You can lock this one too, since you can insert ActionScript code inside it, without it having to be unlocked. Select the first keyframe of the actions layer.
99 Open the Actions panel by selecting Window > Actions. Insert the following code here:
var loadedData:Number = this.getBytesLoaded();
var allData:Number = this.getBytesTotal();
var percentageLoaded:Number = Math.floor(loadedData/allData*100);
mainpreloader_mc.infodisplay_txt.text = "LOADING: " + percentageLoaded + "%";
if (percentageLoaded >= 100) {
gotoAndStop("main", 1);
}
This is an old-school preloader compared to the one you made for loading external content. It fetches the loaded number of bytes via the getBytesLoaded()
method and stores it in the loadedData
variable. The total number of bytes your main Flash movie has is retrieved via the getBytesTotal()
method and is stored in the allData
variable. The ActionScript keyword this
is used to point to the main Flash movie itself, since it resides on the main timeline.
Then, the percentage calculation is done like it was done previously, using some simple maths. The next line after that writes out the information in the dynamic text field, which is inside the mainpreloader_mc
movie clip. The conditional if
statement tells the movie to jump to the main scene (where the site content lies) and stop there once all of the Flash document has been loaded.
But, for this code to work — to be able to actually use the preloader as the loading goes, you must create a small looping animation on this scene.
100 Right-click on frame 2 of the preloader layer and select Insert Frame from the context menu.
101 Now right-click on frame 2 of the actions layer and select Insert Keyframe from the context menu.
You need a keyframe in the actions layer because you are going to insert additional ActionScript code here. The preloader layer needs only a frame, because no changes will be made inside it, it just needs to span the two frames.
102 With the second keyframe in the actions layer selected, open the Actions panel (shortcut key: F9). Insert the following code inside:
gotoAndPlay(1);
This will send the playhead back to to frame 1 of this scene. This will go on (the looping animation), until your Flash movie has been fully loaded. Then the if
conditional statement on frame 1 will turn out as true and will send the playhead to the main scene and stop it there.
And that’s it! You have just finished making a fully working Flash website navigation and loading system! Congratulations!
Conclusion
The menu/loading system that you learned to create with this lesson is just one of many possible solutions for creating an effective Flash navigation system. You can create many variants based on this example, expand on it and build further solutions that are even more modular and extendable.
I hope that what you’ve learned will inspire you to create your own cool Flash menus and preloading systems. You can consult my menus & interfaces tutorials section to see more ways of making website menus in Flash as well as explanations on how to design cool-looking interface parts. Keep on learning!