Flash MX 2004 introduces MovieClipLoader

If you have ever tried to load an external jpeg or swf in to a flash movie, it is likely you will have encountered a situation where you need to trigger an event based upon completion of that loading process.

Loading external data of any kind in to Flash is never instantaneous, therefore it usually gives rise to the need for some sort of checking process - usually in the form of a preloader.

The MovieClipLoader API (Applications Programming Interface) takes away much of the necessary work involved in loading images and swfs in to our Flash movies, and allows us to be notified about the various stages of loading, ultimately giving us more control over our movie, and helping us cut down on the amount of code we need to write.

We can use a single instance of the MovieClipLoader class to load one or more files in to a single movieclip/level, or create a different MCL instance for each file we load.

I have decided to split the subject up in to two seperate tutorials. The first will introduce you to basic MCL usage, and the second will show you how to use a single MovieClipLoader instance to load content in to multiple (duplicated) movie clips, and will employ the use of a listener object. It is possible to use MCL without the need for a listener, and as some of you will not be familiar with how they work you may find it easier to learn about the MovieClipLoader if we ignore using a listener for the time being.

With that said, let's look at what makes the MovieClipLoader class so useful - callback functions. Callbacks are the 'internal organs' of tha MCL class - they are what provide us with the information on the status of the files being downloaded. There are 7 callbacks in all, 5 of them give us infomation about various stages of the loading process. The other two deal with unloading and errors. Let's take a very brief look at them before we proceed:

MovieClipLoader callbacks:

  • MovieClipLoader.onLoadStart() - invoked when loading begins.
  • MovieClipLoader.onLoadProgress() - invoked as the loading process progresses.
  • MovieClipLoader.getProgress() - progress of the downloaded file(s).
  • MovieClipLoader.onLoadInit() - invoked after the actions in first frame of clip have executed.
  • MovieClipLoader.onLoadComplete() - invoked when the entire downloaded file has been written to disk.
  • MovieClipLoader.onLoadError() - invoked if the clip cannot be loaded.
  • MovieClipLoader.unloadClip() - remove movies/images loaded with this method or cancels a load operation in progress.

The list of callback functions and short explanations, though brief, should be pretty self-explanatory, and the best way to learn about the MovieClipLoader class is to jump straight in and get our hands dirty, but before we do there are a couple of things to note.

Firstly, MCL is new to Flash 7, so ensure that Flash is set to export swfs as Flash 7 and using AS2 - the settings for both of these can be found under the FILE->PUBLISH SETTINGS menu. The second important thing to note is that for our MovieClipLoader to function properly we'll need to view it through a browser. If you try and test it directly through Flash your bytesLoaded and bytesTotal values will end up being recorded as zero.

In our example we're going to use a single MovieClipLoader object to load several pictures in to empty movieclips. The swfs and images needed for this example can be found in the sourcefile for this tutorial and can be seen in action here.

Building the Example:

1. Create a new movie (.fla) and put the following code on the first frame of the root timeline:

_root.traceBox.vScrollPolicy ="on";
function myTrace(msg)
        _root.traceBox.text += msg + newline;
        _root.traceBox.vPosition = _root.traceBox.maxVPosition;

All we're doing here is setting up a basic trace function, the output of which will be displayed in the TextArea component that we are about to place on the stage. _root.traceBox.vPosition = _root.traceBox.maxVPosition keeps the scrollbar moving as more content is added, so that we can see new traces as they appear without the need to manually scroll. vScrollPolicy makes sure the vertical scrollbar is on at all times.

2. Now drag an instance of the TextArea component on stage from your components panel, resize it to make it big enough to display our traces properly and give it an instance name of "traceBox".

3. The next step is to create a new movieclip symbol, and place 3 instances of that symbol on the main stage, giving them the instance names of "myMC1", "myMC2" and "myMC3". We will load our images and swfs in to these, so space them about at 200 pixels apart. Our loaded images will actually be much bigger than 200 pixels wide, but we'll resize them once they've downloaded. It is not good practice to make your images larger than the final size at which they will be displayed of course, but for the sake of this tutorial it will allow us to see the onLoadInit() method in action.

4. The next thing to do is to create our new MovieClipLoader object which we'll call myMCL, so add the following code to the first frame, below our trace function:

var myMCL = new MovieClipLoader();//create an instance of MovieClipLoader
5. Okay with that done we're now going to assign our first bit of functionality to our MCL object. If you remember, the onLoadStart method of our class is invoked when loading begins. onLoadStart() receives, as an argument, the name of the movieclip instance calling it. Add the following code to frame 1:
myMCL.onLoadStart = function (targetMC)
        var loadProgress = myMCL.getProgress(targetMC);
        myTrace ("The movieclip " + targetMC + " has started loading");
        myTrace("Bytes loaded at start=" + loadProgress.bytesLoaded);
        myTrace("Total bytes loaded at start=" + loadProgress.bytesTotal);
The first line of code inside our function declares a new variable "loadProgress", to which we assign the results of our getProgress method (getProgress returns an object with two integer properties: bytesLoaded and bytesTotal). The last two traces send these values (bytesLoaded and bytesTotal) to be displayed in our TextArea component.

6. We have already assigned functionality to our onLoadStart() method. Now we will work through the remaining methods that I listed earlier, and see how we assign functionality to those too. Next up is onLoadProgress() which accepts three arguments (the movieclip in question and its byte-loaded details). Again, we send those details to be displayed in our trace function. Add the following code to frame 1:

myMCL.onLoadProgress = function (targetMC, loadedBytes, totalBytes) {
        myTrace ("movie clip: " + targetMC);
        myTrace("Bytes loaded at progress callback=" + loadedBytes);
        myTrace("Bytes total at progress callback=" + totalBytes);
7. Our onLoadComplete method accepts one argument which is the name of the clip. Again, we assign the results of getProgress to a variable and extract the byte details for display.
myMCL.onLoadComplete = function (targetMC)
        var loadProgress = myMCL.getProgress(targetMC);
        myTrace (targetMC + " has finished loading.");
        myTrace("Bytes loaded at end=" + loadProgress.bytesLoaded);
        myTrace("Bytes total at end=" + loadProgress.bytesTotal);
8. The onLoadInit function is not executed until the content has fully loaded in to the movieclip. This makes it the perfect place to put any code which will affect your movieclip's properties. I chose pictures which were quite large for testing purposes, so that we can track the loading progress in the trace box, but we are now going to resize each movieclip so that all the content fits on screen.
myMCL.onLoadInit = function (targetMC)
        myTrace ("Movie clip:" + targetMC + " is now initialized");
        targetMC._width = 170;
        targetMC._height = 170;
9. One of the callbacks we have access to is onLoadError. If an error occurs it returns one of three error messages as a string: "URLNotFound", "LoadNeverCompleted" or "Call Yourself a Programmer?" Okay, make that two.
myMCL.onLoadError = function (targetMC, errorCode)
        myTrace ("ERRORCODE:" + errorCode);
        myTrace (targetMC + "Failed to load its content");
10. Well that's the hard work out of the way. Now we just have to load the files in to their respective targets, using loadClip, and passing it two arguments: the location of your file, and the destination movieclip for the file to load in to.
//load the files in to their respective targets
myMCL.loadClip("http://www.yourdomain.com/test2.swf ", "_root.myMC2");
myMCL.loadClip("http://www.yourdomain.com/pic.jpg", "_level0.myMC3");
Right, change those paths to make them correct for you, publish the file and upload everything to the same directory on your server. I've used absolute paths here but of course relative paths are better used where possible, and if our pictures/swfs are in the same folder as the main swf we would be more likely to type something like:
//load the files in to their respective targets
Now check the results of your hard work in your browser...

If all went well it should look something like my example. If not you can always download the MCL_tutorial.zip and compare the two fla's to see where they differ.

Remember, for everything to work properly you need to be testing throuhg a browser (and preferably on line so you can see the files loading in real time). You also need to be exporting your code as ActionScript 2.

In the second part of this tutorial I'm going to show you how to use the MovieClipLoader class in a real-world situation, in order to solve a common problem when assigning event handlers to MovieClips dynamically.

The second tutorial makes use of a listener object, so it will help if you have a basic understanding of listeners and what they do. If you haven't used listeners before then I can give no stronger recommendation then to read Senocular's excellent tutorial (as are all his tutes by the way) which can be found here.

Completing the second tutorial should solidify all the things we covered here. Have a rest, make yourself a coffee and then if you're ready you can continue... (See the link to Part 2 of this tutorial, at the bottom of this page)