Boris van Schooten

Showing progress bar when loading a large SWF (AS3, Flex 4)

If you have a single large SWF, you often want to produce a custom intro screen (such as a progress bar) while it is loading. This is possible in Actionscript 3, using a factory class, though I found the documentation rather obscure. Thanks to some blog postings and the Mochi API examples I found out how it works.

As an example I will discuss a simple “progress bar” loader that can be plugged into any actionscript class.

First of all, you need to add a Frame pragma in front of your main class, like this:

?View Code ACTIONSCRIPT
package mypackage {
 
[Frame(factoryClass="utils.SimplePreloader")]
public class MyClass extends ... {
   .....
} }

This will load utils.SimplePreloader as the preloader. Now, let’s define this preloader (which is a modified version of Keith Peters’s code):

package utils {
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.utils.getDefinitionByName;
 
public class SimplePreloader extends MovieClip {
 
public function SimplePreloader() {
    stop();
    addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(event:Event):void {
    graphics.clear();
    if (framesLoaded == totalFrames) {
        removeEventListener(Event.ENTER_FRAME, onEnterFrame);
        nextFrame();
        init();
    } else {
        var percent:Number = root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal;
        graphics.beginFill(0xffffff);
        graphics.drawRect(10, stage.stageHeight / 2 - 10,
        (stage.stageWidth-10) * percent, 20);
        graphics.endFill();
    }
}
private function init():void {
    // We take the class name from a compiler definition. Note that we must
    // NOT reference the class directly (i.e. no "new MyClass()").
    // A direct reference will make the preloader wait until the class is loaded!
    var cls:Class = Class(getDefinitionByName(CONSTANTS::MainClass));
    var app:Object = new cls();
    addChild(app as DisplayObject);
    // Note we call init here, or anything else you need to init your class.
    app.init();
}
 
} }

Note that this preloader does not work with any class. The class must not reference the stage until it is added to the scene tree with addChild. Stage will be null until then.

Finally, here are the compiler switches. Note that we cannot set background colour or size using the [SWF...] pragma, because you cannot have both Frame and SWF pragmas at the same time. So, we set them using compiler switches. The main class is passed through a ‘-compiler.define’ switch.

?Download make.bash
mxmlc  \
  -static-link-runtime-shared-libraries=true -debug=true -verbose-stacktraces \
  -source-path=.  mypackage/MyClass.as \
  -default-size 640 480 \
  -default-background-color 0 \
  '-compiler.define=CONSTANTS::MainClass,"mypackage.MyClass"'