AS Reference  :  Notes Index  :  Resources  :  About/Contact  :  Downloads

Including external JPGs (or SWFs) in a Flash movie




Movie generated completely from code, displayed below

To keep your published Flash movie size down, or because you have graphic content that will vary, it's often desirable to use picture files that are external to the Flash file. Instead of putting them in movieclips in the library and having to wait for them all to load before the movie can begin, you can load them at runtime, either all upfront as in the example above, or individually whenever they are needed. As of Flash MX 2004, Flash can read only non-progressive jpg's, not gifs or pngs or any other format, from an external directory. To include other files dynamically, you'd need to publish a swf with the graphic you want and then load that swf, using the same method that will be described below for loading jpgs.

Option 1: loadMovie

The simplest way to load a jpg or an external swf is with the loadMovie command, in which you specify the movieclip you want to load into, and the path and name of the file to be loaded. Eg

holder_mc.loadMovie("../summer/camping.jpg");
which would load camping.jpg from the summer directory, a directory at the same level as the one with the html page that has the Flash movie, into holder_mc.

Directory path to jpg
Note that the path to the picture to be loaded is relative to the html page holding the swf that's doing the loading, not relative to the swf itself. This is only relevant if the html page and swf embedded in it are in different directories.

Because the jpg is being loaded from a directory on a web server down to a viewer's pc, it takes some time for the loading to complete. No positioning or scaling of holder_mc (ie, its new content) may be done until the loading is complete. The main drawback of the loadMovie command is that there is no built-in way to tell when loading is complete, so some sort of loop must be set up to check for loading complete if anything is to be done to the jpg or swf after it is loaded.

Another pitfall of loadMovie is that it causes any properties of the movieclip being loaded into to be wiped out when the new content has been loaded, including any event handlers or other functions that may have been assigned to the movieclip.

Option 2: MovieClipLoader plus Listener

The MovieClipLoader class, introduced in Flash MX 2004, provides a neat way around these problems. To use this method to load a jpg, a swf, or series of jpgs or swfs, you do the following

  1. create an instance of the MovieClipLoader class,
  2. (create if necessary and) designate a Listener which will listen for and respond to events issued by the MovieClipLoader instance, and
  3. create functions that will do the things you want to do while the jpg is loading and when it has been completely loaded.
  4. start the download

The combination of Listener and functions you set up take the place of the wait loop that would otherwise be required (if you used the old way, loadMovie). The use of a MovieClipLoader eliminates the need for a holder movieclip within the movieclip you load into.

Here is a little demo of the steps that needs to be done, and how each element is used in the movie after the request to load the movie is done. Below that is a more detailed explanation.

loadClip (MovieClipLoader method)

The MovieClipLoader class has a method, loadClip, which is used to initiate the loading. This method takes two parameters, one that specifies the path (relative to the html page in which your main swf is embedded) and filename of the jpg or swf to be loaded, and a second which is a reference to the movieclip to be loaded into.

onLoadProgress (Listener function)

Once that loadClip command has been issued, Flash starts downloading the jpg or swf from the web server. While that download is happening, the MovieClipLoader instance broadcasts messages (automatically; you don't have to do anything to make that happen) that the Listener can listen for and respond to with its onLoadProgress function. This onLoadProgress function, therefore, needs to be defined before the download is initiated.

onLoadProgress is a method which accepts 3 parameters, in this order: a reference to the movieclip into which the jpg or swf is being loaded, the number of bytes that have downloaded so far, and the total number of bytes in the file being downloaded. This information can be used to set up a loading progress indicator while the download is happening (eg, the text percent indicator in the example above). The parameters can be given whatever names you want, as long as you use the same names throughout the onLoadProgress routine; they will always refer to the movieclip, bytes loaded and bytes total, respectively.

onLoadInit (Listener function)

Once the download is complete, the MovieClipLoader instance broadcasts a message saying that the jpg or swf has been received and is ready to be executed (eg, for a swf with a stop action in frame 1), resized, repositioned, made invisible or visible, or anything else that needs to be done once the file has been completely downloaded. The function that the Listener uses to respond to that broadcast message is onLoadInit.

The Listener

We mentioned above that you need to have a Listener which listens for events broadcast by the MovieClipLoader instance and responds to them. You can either create a separate object to act as a Listener, as is done in the Flash Help documentation examples, or you can use the main timeline or some other already-existing object to act as your Listener. On this page, I have chosen to do the latter, because the code is then more easily extensible for use in a custom class.

Putting it all together

Here's an outline of the (commented) code needed to load a picture or swf using MovieClipLoader with the main timeline as the Listener:

MovieClipLoader + Listener framework
For cut and paste when setting up code to load a jpg or swf

// set up loader, an instance of MovieClipLoader, and use the main timeline ("this")
// to listen to and respond to its broadcast events
var loader:MovieClipLoader = new MovieClipLoader();
loader.addListener(this);

// define what should happen when the jpg/swf is completely loaded
// use _mc to refer to the loaded jpg/swf
function onLoadInit(_mc:MovieClip) {
   // code here
};

// define what should happen while the jpg/swf is loading
// use _mc to refer to the jpg/swf and loaded & total to refer to the number of bytes
// currently loaded and to be loaded, respectively
function onLoadProgress(_mc:MovieClip, loaded:Number, total:Number) {
   // code here
};

// start loading specified jpg/swf into blank movieclip holder_mc on stage
loader.loadClip("somepic.jpg", holder_mc);

And here's the framework expanded into an actual example. This code loads a jpg into holder_mc (a movieclip on stage), displaying the percent loaded in pct_txt inside pct_mc (put inside a movieclip so that it can be hidden when done), and showing the jpg at half size when loaded:

MovieClipLoader + Listener example
Show load progress, resize when loaded

// set up loader, an instance of MovieClipLoader, and use the main timeline ("this")
// to listen to and respond to its broadcast events
var loader:MovieClipLoader = new MovieClipLoader();
loader.addListener(this);

// define what happens when the jpg is completely loaded
function onLoadInit(_mc:MovieClip) {
   _mc._xscale = 50;
   _mc._yscale = 50;
   pct_mc._visible = false;
};

// make pct_txt show cumulative loading progress
function onLoadProgress(_mc:MovieClip, loaded:Number, total:Number) {
   pct_mc.pct_txt.text = Math.floor(loaded / total * 100) + "%";
};

loader.loadClip("oahupics/hanauma.jpg", holder_mc);

Notice that we used onLoadInit's one parameter (a reference to the movieclip being loaded into), to access the movieclip being loaded into (that is, to access the newly-loaded jpg or swf itself). You can use any name you like for that parameter (I used _mc) but it will always refer to the movieclip being loaded into. Likewise, we used the 3 parameters that onLoadProgress has built into it to access the movieclip being loaded into, the number of bytes loaded and the total number of bytes. You don't have to have an onLoadProgress function -- you only need it if you want to be able to do something while your file is downloading from the web server. (If you're running the Flash movie locally and accessing local jpgs or swfs, the onLoadProgress function will never be called, since the files are not being downloaded from a web server.) Likewise, you don't have to set up an onLoadInit function -- only if you need to do something to the jpg or swf (or anything else in the movie, like hiding the preloader as we did above) once it has loaded.

Both of the listener's handler functions should be set up (defined) before the loadClip command is issued, so that they will be ready to handle any events issued by by loader.

Testing within the Flash IDE:
To test and see whether your onLoadProgress function is working before you upload the files to your server, you need to simulate a web server download (because when run locally, Flash will grab the files from your hard drive and onLoadProgress will never be called). To do that in Flash 8 (it doesn't work in Flash MX 2004), choose Control, Test Movie. Then choose View, Download Settings and check one of the settings shown. Then choose View, Simulate Download and your movie will display as though it is being served from a web server at that connection speed.

Loading multiple jpg's, sequentially

That was pretty straightforward (well, as straightforward as you can get with asynchronous file transfers happening while your movie is running). If you want to preload a number of jpgs, things get a bit more complicated. Because you should only have one jpg (or swf) loading at a time, your onLoadInit routine has to be set up to start the next jpg loading when one is complete. The easiest way to do that is to use an array with the names of all the jpgs you want to load, and a variable on the main timeline (ipic in the code below) that keeps track of which element of the array is currently being loaded. Below is the code to generate the whole movie shown above from scratch (nothing on stage, nothing in the library -- just start with a 420 x 290 movie with a black background, 20fps, and jpgs in the specified folder (relative to the html) of the specified names, put the code below in frame 1 and you've got a ready-made photo viewer.

Other things to note about the code below are the use of createEmptyMovieClip to create a holder for the main pictures (which will be loaded with loadMovie since no further positioning or sizing of them needs to be done after load), and for a thumbs movieclip that will hold the thumbnails. Another method of the MovieClip class, createTextField (which creates an instance of the TextField class in the specified movieclip), is used to create a percent loaded indicator, and then removed when all the loading is done.

/*********  DECLARE AND INITIALIZE VARIABLES  **************************/
// names of folder and pictures, in the order to put them into the thumbnails holder
var picnames:Array = [
	"flower_orange", 
	"flower_yellow", 
	"flower_pink", 
	"flower_red", 
	"flower_purple"];

// constants
var PICPATH:String = "flowers/";	// folder with jpgs
var NPICS:Number = picnames.length;	// number of pictures to load
var PICX:Number = 10;               // x loc of big picture
var PICY:Number = 10;               // y loc
var THUMBHOLDERX:Number = 0;        // x location of thumbnail holder movieclip
var THUMBHOLDERY:Number = 230;      // y location
var THUMBW:Number = 72;             // width of each thumbnail
var THUMBH:Number = 40;             // height
var MARGIN:Number = 10;             // margin between thumbnails
var TOTALBYTES:Number = 106000;     // approx sum of bytes in all jpgs 

var totalloaded:Number = 0;         // running tally of bytes loaded from all pics

// index into pictures array, used for loading
var ipic:Number;

// set up loader, an instance of MovieClipLoader
var loader:MovieClipLoader = new MovieClipLoader();

// use the main timeline to listen to and respond to loader's broadcast events
loader.addListener(this);

/*********  DEFINE FUNCTIONS, INCLUDING INIT FOR MOVIE SETUP  **********/
// thumbnail rollover handler

function grow() {
   this.onEnterFrame = function() {
      if (this._width < THUMBW * 1.2) {
         this._x -= this._width * .025;
         this._y -= this._height * .025;
         this._width *= 1.05;
         this._height *= 1.05;
      } else delete this.onEnterFrame;
   };
}

// thumbnail rollout handler

function shrink() {
   this.onEnterFrame = function() {
      if (this._width > THUMBW) {
         this._width /= 1.05;
         this._height /= 1.05;
         this._x += this._width * .025;
         this._y += this._height * .025;
      } else delete this.onEnterFrame;
   };
}

// thumbnail click (onrelease) handler

function openPic() {
   pic_mc.loadMovie(PICPATH + picnames[this.i] + ".jpg");
}

// assign event handlers (called when all jpgs are loaded)

function setupHandlers() {
   pct_txt.removeTextField();		// don't need loading indicator any more
   for (var i:Number = 0; i < NPICS; i++) {
      thumbs_mc["mc"+i].onRollOver = grow;
      thumbs_mc["mc"+i].onRollOut = shrink;
      thumbs_mc["mc"+i].onRelease = openPic;
   }
}

// listener function for broadcast 'done' message (for each pic)
// onLoadInit gets executed when the movieclip has been loaded into _mc AND 
//   its width and height data are available.
//   (_mc = the movieclip being loaded into)
// this routine sets the size and position of each thumbnail clip as its jpg
//   is loaded and starts the next one loading.  When all have been loaded, 
//   a random picture is loaded into pic_mc and setupHandlers is called to 
//   assign handlers to each thumbnail movieclip

function onLoadInit(_mc:MovieClip) {
   // this gets done when the jpg is completely loaded:
   _mc._width = THUMBW;
   _mc._height = THUMBH;
   // give the movieclip a property to remind it who it is
   // (used by openPic to know which big picture to open)
   _mc.i = ipic;
	
   // add picture size to totalloaded variable
   totalloaded += loader.getProgress(_mc).bytesTotal;

   // now load the next one (if there are more) or set up handlers if done
   ipic++;
   if (ipic == NPICS) {
      // start with a random photo displayed
      pic_mc.loadMovie(PICPATH + picnames[Math.floor(Math.random()*5)] + ".jpg");
      setupHandlers();
   } else {
      loader.loadClip(PICPATH + picnames[ipic] + ".jpg",  thumbs_mc["mc"+ipic]);
   }
};

// listener function to handle broadcast progress messages
// make pct_txt show cumulative loading progress

function onLoadProgress(_mc:MovieClip, loaded:Number) {
   var loadedsofar:Number = totalloaded + loaded;	
   pct_txt.text = Math.floor(loadedsofar / TOTALBYTES * 100) + "%";
};

// things to do to set up the stage and start the movie:
// create holders for the pictures and thumbnails
// create and format progress-indicating textfield
// create individual holder movieclips for each thumbnail within the thumbnail holder
// start the pictures loading with loadClip

function init() {
   // create holder for pictures
   createEmptyMovieClip("pic_mc", 1);
   pic_mc._x = PICX;
   pic_mc._y = PICY;

   // create (and draw) holder for thumbnails
   createEmptyMovieClip("thumbs_mc", 2);
   thumbs_mc.beginFill(0, 100);
   thumbs_mc.moveTo(0, 0);
   thumbs_mc.lineTo((MARGIN + THUMBW) * NPICS, 0);
   thumbs_mc.lineTo((MARGIN + THUMBW) * NPICS, THUMBH + 2 * MARGIN);
   thumbs_mc.lineTo(0, THUMBH + 2 * MARGIN);
   thumbs_mc.endFill();
   thumbs_mc._x = THUMBHOLDERX;
   thumbs_mc._y = THUMBHOLDERY;

   // create loading textfield indicator
   createTextField("pct_txt", 3, 200, 100, 40, 100);
   var tf:TextFormat = new TextFormat();
   tf.align = "center";
   tf.size = 12;
   tf.font = "Verdana";
   tf.color = 0xFFFF00;
   pct_txt.setNewTextFormat(tf);

   // make empty movieclips in thumbs_mc for each pic to go into
   for (var i:Number = 0; i < NPICS; i++) {
      var mc:MovieClip = thumbs_mc.createEmptyMovieClip("mc"+i, i+1);
      mc._x = MARGIN + i*(MARGIN + THUMBW);
      mc._y = MARGIN;
   }

   // set the pointer to the first jpg in the array picnames
   ipic = 0;
   // start loading jpgs 
   loader.loadClip(PICPATH + picnames[ipic] + ".jpg", thumbs_mc["mc"+ipic]);
}

/*********  CALL THE INIT FUNCTION TO START THE MOVIE  *****************/
init();

The next page expands on this sample to make a thumbnail slider which can accommodate any number of photos in a folder.

Intro
Flash: What & How
Example Sites
Create
Draw, Edit Shapes
Gradients
More Drawing Tips
Import
A Sample
Animate
Frames, Keyframes
Motion Tweens
More Motion Tweens
Shape Tweens
Masks
Control
Stop/Replay
Movieclips Intro
Movieclip Reference
Site Structure 1
Slideshow Movieclip
Contact Form
Scroll Resume
Preloader
Site Structure 2
Publish
Display Options
Player Detection
Optimize
AS 2.0 Basics
Intro to Syntax
Playhead Commands
Playhead Cmds 2
Coded Tween
onEnterFrame
Intro to Classes
Declare/Assign
Comments, Trace
Simple Data Types
Arrays & Objects
Code Blocks
Operators
Beyond Buttons
Code Structure
Toggle Controls
Group of Buttons
Drag and Hit
Distort Magnifier
Scroll Text
Bee Game
Dart Shooter
Sound Control
Easing Slider
Easing Slider 2
Components Intro
Timers & Delays
Dynamic Content
Intro
Drawing API
Create Text
Attach Movieclips
Easing Slider 3
Easing Slider 4
Load jpg/swf
Sliding Viewer
Preload swf
XML
Easing Slider 5
Server Comm
LoadVars (w/ PHP)
AS - PHP Lookup
Text File
Database 1:LoadVars
Database 2:Remoting
Read from directory
AS 2.0 Classes
Intro
Math
Key
Date
Color
EventDispatcher
New Samples
Pie Chart
Event-model Emailer
Tween Sequence
Fuse Sequence
SVG in Flash
Bitmap Topo
SWF as Data Holder
Two-level Menu
Yahoo! Flash Maps
Class-based Game
ASTB Samples
Disclaimer
3D Outlines
Bounce Collide
Address Book
Save Drawings
Home  :  Notes Index  :  Resources  :  About/Contact  :  Downloads