AS3 Loader for Loading Multiple External Files

– taterboy | November 3rd, 2010

Filed under: ActionScript 3, Flash, Flex, Tutorials

LoaderCollection:
Loading multiple files with a single progress loader that displays the total loading percentage of all items being loaded.


Get Adobe Flash player


Demo Version, not actual component

Before we get into the LoaderCollection, let’s discuss how you load single external files. The LoaderCollection recognizes Flash’s Loader class as well as a custom class called SimpleLoader.

The SimpleLoader:
The process of loading an external file such as an SWF or Bitmap file is as follows.
1. Import the SimpleLoader class, I know it is not really that simple.
2. Create a new instance of SimpleLoader passing a minimum of 2 arguments.
A: parentObject (required): once the file is loaded, it will be added as a child to this object – parentObject.addChild(loadedObject);
B: contentURL (required): url path to the file to be loaded
C: objectName: the name you will use to target the loaded object – parentObject[objectName].width; available on load complete.
D: monitorFunction: a callback function were all loading progress is sent. – returns percent:int (0 – 100) and tag:String
E: tagString: A string to use as display text or unique id when multiple items are loaded.
3. Add a function to receive loader progress, expects percent:int and tag:String.

Usage Example:

?View Code ACTIONSCRIPT
import com.hdi.loaders.SimpleLoader;
import com.hdi.loaders.LoaderCollection;
 
/** loading an external asset using SimpleLoader **/
 
//reserve the object name for the loaded object - optional.
var myLoadingSWF:Object;
 
/**
 * new SimpleLoader
 * @param parentObj: parent for loaded item - required
 * @param contentURL: url path of content to load - required
 * @param objectName: the target name of the final loaded object
 * @param monFunction: function to callback with loader progress
 * @param tagString: description or label of currently loading item - loader display text
 **/
var loader:SimpleLoader = new SimpleLoader(this,"mySWF.swf", "myLoadingSWF", simpleLoaderCallback, "SWF");
 
//loading monitor function - expects percentage (0 - 100), tag (string)
function simpleLoaderCallback(perc:int, tag:String):void{
	trace("Percentage Loaded: " + perc);
	trace("Loading Tag: " + tag);
 
	if(perc == 100){
		trace("Loading Complete");
		trace("Loaded Item Reference: " + myLoadingSWF.name);
	}
}

Note: There are two options for targeting objects once they are loaded. ex: parentObject[objectName].width or parentObject.objectName.width. For the latter format to work, you must add a place holder object reference like so: var objectName:Object;

The Class:

?View Code ACTIONSCRIPT
package com.hdi.loaders{
 
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.events.ProgressEvent;
 
	public class SimpleLoader{
 
		public var url:String;								//url string
		public var callback:Function = null;				//callback function or loading monitor - returns @percent (int 0 - 100), @tag (String from SimpleLoader)
		public var tag:String = "";							//tag string of loading item
		public var objName:String;							//object name for final loaded object
		public var objParent:Object;						//parent for final loaded object
		public var percent:int;								//percentage of loaded content
		private var ldr:Loader;								//loader class
 
		/**
		 * init
		 * @param parentObj: parent for loaded item
		 * @param contentURL: url path of content to load
		 * @param objectName: the target name of the final loaded object
		 * @param monFunction: function to callback with loader progress
		 * @param tagString: description or label of currently loading item
		 **/
		public function SimpleLoader(parentObj:Object, contentURL:String, objectName:String = "", monFunction:Function = null, tagString:String = ""){
 
			callback = monFunction;
			url = contentURL;
			objName = objectName;
			objParent = parentObj;
			tag = tagString;
 
			//load items and setup event listener
			ldr = new Loader();
			ldr.load(new URLRequest(contentURL));
			ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loadingComplete);
			ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadingProgress);
		}
 
		/**
		 * on loading complete
		 * @param event: Event
		 **/
		private function loadingComplete(ev:Event):void{
 
			//add item to parent and add object name
			if(objParent != null){
				var obj:Object = ev.target.content;
				objParent.addChild(obj);
				if(objName.length > 0){
					objParent[objName] = obj;
				}
				ldr.unload();
			}
 
			//set percent to 100 and callback
			percent = 100;
			if(callback != null){
				callback(100, tag);
			}
 
			//remove event listeners
			if(ev.target.hasEventListener(Event.COMPLETE)){
				ev.target.removeEventListener(Event.COMPLETE, loadingComplete);
			}
			if(ev.target.hasEventListener(ProgressEvent.PROGRESS)){
				ev.target.removeEventListener(ProgressEvent.PROGRESS, loadingProgress);
			}
		}
 
		/**
		 * on loading progress
		 * @param event: ProgressEvent
		 **/
		private function loadingProgress(ev:ProgressEvent):void{
 
			//update percent
			percent = Math.floor((ev.bytesLoaded / ev.bytesTotal)*100);
			if(callback != null){
 
				//callback updated percentage
				if(percent < 100){
					callback(percent, tag);
				}
			}
		}
	}
}

The LoaderCollection:
To monitor the loading progress of multiple loading items at once, follow these steps:
1. Import the LoaderCollection Class
2. Create and instance of LoaderCollection passing a reference to the function that will be used to monitor loading progress.
3. Add each loader to the LoaderCollection, for best results do this in one frame

Usage Example (SimpleLoader):

?View Code ACTIONSCRIPT
import com.hdi.loaders.SimpleLoader;
import com.hdi.loaders.LoaderCollection;
 
/** loading Multiple items using SimpleLoader **/
 
//reserve the object name for the loaded object - optional.
var myLoadingSWF:Object;
var myLoadingBMP:Object;
 
/**
 * new LoaderCollection
 * @param callback: funciton to call on loader updates
 **/
var loaderManager:LoaderCollection = new LoaderCollection(loaderCallback);
 
// new SimpleLoaders
var loader1:SimpleLoader = new SimpleLoader(this,"mySWF.swf", "myLoadingSWF", null, "SWF");
var loader2:SimpleLoader = new SimpleLoader(this,"myBMP.jpg", "myLoadingBMP", null, "BMP");
 
//add Simple Loaders to LoaderCollection
loaderManager.addSimpleLoader(loader1);
loaderManager.addSimpleLoader(loader2);
 
//loading monitor function from LoaderCollection - expects percentage (0 - 100), tag (string)
function loaderCallback(perc:int, tag:String):void{
	trace("Percentage Loaded: " + perc); //average loaded of all loading files
	trace("Loading Tag: " + tag);	//tag name for display of one of the currently loading files.
 
	if(perc == 100){
		trace("Loading Complete"); // all items in the collection have been loaded, the LoaderCollection will no longer work at this point.
	}	
}

UsageExample (Loader):

?View Code ACTIONSCRIPT
import com.hdi.loaders.SimpleLoader;
import flash.display.Loader;
 
/** loading Multiple items using flash.display.Loader **/
var loaderManager:LoaderCollection = new LoaderCollection(loaderCallback);
 
//create new loader and load files as normal.
var loader1:Loader = new Loader();
loader1.load(new URLRequest("myLoadingSWF.swf"));
addChild(loader1);
 
var loader2:Loader = new Loader();
loader2.load(new URLRequest("myLoadingBMP.jpg"));
addChild(loader2);
 
// add loaders to LoaderCollection
loaderManager.addLoader(loader1);
loaderManager.addLoader(loader2);
 
//loading monitor function from LoaderCollection - expects percentage (0 - 100), tag (string)
function loaderCallback(perc:int, tag:String):void{
	trace("Percentage Loaded: " + perc); //average loaded of all loading files
	trace("Loading Tag: " + tag);	//empty string when not using SimpleLoader.
 
	if(perc == 100){
		trace("Loading Complete"); // all items in the collection have been loaded, the LoaderCollection will no longer work at this point.
	}
 
}
 
stop();

Note: Once the LoaderCollection reaches 100% all the functionality of the class is automatically disabled.

The Class:

?View Code ACTIONSCRIPT
package com.hdi.loaders{
 
	import flash.events.Event;
	import flash.display.Loader;
	import flash.display.MovieClip
 
	public class LoaderCollection extends MovieClip {
 
		public var loaderList:Array = [];								//array of added loaders
		private var callbackFunc:Function = null;						//function to callback on loader updates - returns @percent (int 0 - 100), @tag (String from SimpleLoader)
		public var percent:int;											//@percent (int 0 - 100)
		public var tag:String = "";										//@tag (String from SimpleLoader) currently loading item tag
		var index:int;													//index of loading items in loaderList;
		/**
		 * init
		 * @param callback: funciton to call on loader updates
		 **/
		public function LoaderCollection(callback:Function):void{
			callbackFunc = callback;
			this.addEventListener(Event.ENTER_FRAME, loaderHandler);
		}
 
		/**
		 * add SimpleLoader instance to LoaderCollection
		 * @param loader: SimpleLoader
		 **/
		public function addSimpleLoader(loader:SimpleLoader):void{
			loaderList.push(loader);
		}
 
		/**
		 * add Loader instance to LoaderCollection
		 * @param loader: Loader
		 **/
		public function addLoader(loader:Loader):void{
			loaderList.push(loader);
		}
 
		/**
		 * stop loader updates and cleanup eventlisteners
		 **/
		public function cleanup():void{
			if(this.hasEventListener(Event.ENTER_FRAME)){
				this.removeEventListener(Event.ENTER_FRAME, loaderHandler);
			}
			loaderList = [];						//reset loaderList
		}
 
		/**
		 * figure out average percent of all loading items
		 * @param event: Event
		 **/
		private function loaderHandler(ev:Event):void{
			//trace(this.name);
 
			var perc:int = 0;						//average percent of loaded items
			var ldrs:int = loaderList.length;		//number of currently loading items
			var inc:int;							//percent loaded of loader
 
			//has loading items
			if(loaderList.length > 0){
 
				var ldr:* = loaderList[index];			//loading item
 
				// update tag if SimpleLoader
				if(ldr is SimpleLoader){
					tag = ldr.tag;
				}
 
				for(var p:String in loaderList){
					ldr = loaderList[p];			//loading item
					inc = 0;
 
					//update percent increment
					if(ldr is SimpleLoader){
						inc = ldr.percent;
					}
					else{
						if(ldr.contentLoaderInfo != null){
							inc = Math.floor((ldr.contentLoaderInfo.bytesLoaded/ldr.contentLoaderInfo.bytesTotal)*100);
						}
					}
 
					if(inc > percent && inc < 100){
						index = int(p);
					}
 
					//update percentage
					perc += inc;
 
					//clear fully loaded items
					if(inc == 100){
						//loaderList.splice(int(p),1);
					}
				}
 
				//update percentage and callback updated loading info
				percent = Math.floor(perc/ldrs);
				callbackFunc(percent, tag);
 
				//cleanup Collection once all items are loaded
				if(percent == 100){
					cleanup();
				}
			}
		}
	}
}

Thanks for reading,
What are some other loading tips or components?

Technorati Tags: , , , , , , ,

| No Comments » | facebook:

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

*