Hey everyone,
in the last chapter we made it to load a SWF and unload it on demand. Let's continue here and imagine that we're having three SWFs, each of them having some content which should be shown on click. A typical usage would obviously be a Flash Website consisting of multiple SWFs.
What we're going to do:
At the end of this article we're having three SWFs loaded which can be displayed seperately on click. Sounds pretty trivial but takes some management as well. If you are just interested in that "loading and displaying" click here to scroll to the bottom.
Why is here so much text?
Much of this article doesn't really cover this single purpose but is more going into the general question of how to handle multiple loading-processes. I have seen many Flash projects with a cruel loading management which definetly leads into a "I don't like Flash" attitude. Knowing how to load data is something the HTML world doesn't really have to take care for but we do have and we should think about how to use this option. We can give the user the feeling of getting much content without waiting, we just have to check when it's time to load this.
Thoughts about storing data or always un- & reload it:
My experiences showed me that loading Flash data only on click is one of the most reasons people don't like flash. Why not using the time the user spent on the website to prepare the rest of the content? In 9 of 10 projects that left my table the customer wanted it like everyone's liking it: We're loading data and store it in the cache - just like any video streaming does and not "Why is there again and again a Preloader?" Of course this strongly depends on the project. It doesn't make sense to cache videos or a large amount of images if this would lower the overall performance. Leads me to the general question:
When to load content?
At the very first you have to decide whether to load every Data at once and after all loading processes are done start showing the content or loading just the first files, showing content pretty fast and then start loading the rest in the background while the user can already read content.
Loading the entire content is useful when dealing with a complete size of 2-3MB. The user has to wait in the beginning but then can be sure everything is loaded. I've to admit that I don't use this way too often, the reason is simple: You can do so in one SWF then as well and it makes the whole page work better together. Anyway, the good thing about using multiple SWFs is that you can easily update content without compiling the whole project again and besides working in a team on that is much easier.
Let's check the other option: Loading the first SWF (or the small-sized first, nevermind), adding it to stage and loading the rest in the background. This way can be pretty useful when having slightly bandwith-using content, e.g. a gallery. Does the user really have to wait for the gallery when he opens the site? He might be waiting for 20mb but the site is 1mb without the gallery. So loading it after the rest is absolutely necessary - but wouldn't it be annoying as well if the gallery would start loading only on click? You've then got to wait for it to completely load but you spent already some time on the website - so why not use this time to load the gallery in the background? I'd say this is a big advantage of Flash to load content the user will see. Imagine following: The user opens your website, waiting some seconds for the first content. Then he's spending 30 seconds on it - enough time for the gallery to complete loading. He clicks on gallery and there it is, on click and he didn't even had to wait.
Conclusion to that:
In most cases a mix of both is the right way. You're going to load all the small content elements, such as news, contact, whatever - and load the heavy data like portfolios, galleries, videos, ... at last. The user will not be disappointed when he's seing the gallery-preloader at 60% when clicking it at first but he will continue surfing on the rest of the page till the gallery is loaded. The best case would be that the gallery is completely loaded when the user clicks of course. You've got to find the way in between performance lowering because of caching too much and serving content on demand. Keep in mind that doing this kind of load-management requires some coding knowledge as you have to work with multiple loaders called by different times. But hang on, this will be the #3 on this article series.
Now finally back to the topic: Let's load some SWFs and display it on click.
Load multiple SWFs and store them
As said I'm going to cover the complexity of having different loading processes managed in the next chapter, so at first we're going to load every SWF in the beginning, storing them and show them when wanted. Let's declare some variables first.
-
var _swfPathArr:Array = new Array("00.swf", "01.swf", "02.swf");
-
var _loadedSWFs:int;
-
-
var _swfClipsArr:Array = new Array();
-
var _swfTempClip:MovieClip;
Pretty self-explaining I guess. The temporary MovieClip will be used to quickly store the data (mainly for reasons of adding additional things to it while defining. You'll see in a minute) Now we'll call the function which will start the whole process.
-
startLoading(_swfPathArr);
-
-
function startLoading(pathArr:Array):void {
-
_swfLoader = new Loader();
-
_swfRequest = new URLRequest();
-
-
loadSWF(pathArr[0]);
-
}
-
-
function loadSWF(path:String):void {
-
setupListeners(_swfLoader.contentLoaderInfo);
-
-
_swfRequest.url = path;
-
_swfLoader.load(_swfRequest);
-
}
-
-
function setupListeners(dispatcher:IEventDispatcher):void {
-
dispatcher.addEventListener(Event.COMPLETE, onSwfComplete);
-
dispatcher.addEventListener(ProgressEvent.PROGRESS, currentSwfProgress);
-
}
-
-
function currentSwfProgress(event:ProgressEvent):void {
-
var _perc:int = (event.bytesLoaded / event.bytesTotal) * 100;
-
// swfPreloader.percentTF.text = _perc + "%";
-
}
Using just one Loader instance for all files:
You might have noticed yet that we've got only one Loader instance yet to load each SWF after another. This is because it's making much more sense in this case than loading all files at the same time with multiple loaders. You've got much more control about every loading process, it's easier to determine errors and the speed remains the same. Besides it's much easier to code.
But nevertheless there are cases in which you definetly should work with many instances, e.g. a gallery with many images. I'm going to get into that deeper in the next article as well.
Do the loop and storing
The loader shall continue loading the SWFs while the completely loaded are stored - until every SWF is stored and then the first SWF can be added to stage. The onSwfComplete function is called the first time after - you might know - the first SWF is completely loaded :)
-
function onSwfComplete(event:Event):void {
-
event.target.removeEventListener(Event.COMPLETE, onSwfComplete);
-
event.target.removeEventListener(ProgressEvent.PROGRESS, currentSwfProgress);
-
-
_swfTempClip = event.target.content;
-
_swfTempClip.customID = _loadedSWF;
-
-
_swfClipsArr.push(_swfTempClip);
-
-
if(_loadedSWFs <_swfPathArr.length - 1) {
-
_loadedSWFs++;
-
loadSWF(_swfPathArr[_loadedSWFs]);
-
} else {
-
onCompletePreloading();
-
}
-
}
We're removing the EventListener at first. Just to make sure, you know. Then we're setting the _swfTempClip to the SWF we've just successfully loaded and add an ID to it. Only to check if everything works fine later on. We're pushing it into our Array to store it - the temp clip will be overwritten the next time, but the already loaded one was pushed into our Array. Then the loop is triggered. If the count (which started at 0) is below the count of SWFs we wanna load, we're going to start the loading of the next swf. We're passing the new path as _count is now 1, therefore the second path is used. When every SWF is loaded the onPreloadComplete(); function is called.
Let's imagine we've got three buttons to show the different SWFs. We know for sure, that the first file we've declared in our _swfPathArray has got the Array-Index 0 in our _swfClipsArr. So we can easily access it with _swfClipsArr[0]. To make this really usable for the Flash IDE (don't throw stones on me loved FDT users :)) we're going to easily switch the button's name to load the correct SWF. Besides we've got a MovieClip called "contentContainer" on the stage (yea, the visual stage with a named MC in the Properties!) which holds the SWF.
-
function onCompletePreloading():void {
-
contentContainer.addChild(_swfClipsArr[0]);
-
-
news_btn.addEventListener(MouseEvent.CLICK, setContent);
-
portfolio_btn.addEventListener(MouseEvent.CLICK, setContent);
-
contact_btn.addEventListener(MouseEvent.CLICK, setContent);
-
}
-
-
function setContent(event:MouseEvent):void {
-
var _swfToAdd:MovieClip;
-
-
switch(event.target.name) {
-
case "news_btn":
-
_swfToAdd = _swfClipsArr[0];
-
break;
-
-
case "portfolio_btn":
-
_swfToAdd = _swfClipsArr[1];
-
break;
-
-
case "contact_btn":
-
_swfToAdd = _swfClipsArr[2];
-
break;
-
}
-
-
contentContainer.removeChildAt(contentContainer.numChildren-1);
-
contentContainer.addChild(_swfToAdd);
-
trace(_swfToAdd.customID);
-
}
It's simple as that. We're removing the old SWF from the stage (by determing it to be the last Object added to the MC) and add the new one. The _swfClipsArr's index is equal to the _swfPathArr entries. The trace at the end shows that we're still having control of custom properties we gave our loaded SWFs.
The result:
You can easily test it yourself. Create three SWFs and one loading-SWF. Create three MCs (for the buttons) and an empty MC (as contentContainer) on the loading-SWF's stage. Name the MCs properly and copy the following snippet to your first frame. If you didn't know yet: Testing to display loaded files (from 1MB upwards) in Flash locally cause a lag while adding it to stage. But testing online gives the wanted result. The SWF is changed directly on click.
Here it is:
-
var _swfLoader:Loader;
-
var _swfRequest:URLRequest;
-
-
var _swfPathArr:Array = new Array("00.swf", "01.swf", "02.swf");
-
-
var _swfClipsArr:Array = new Array();
-
var _swfTempClip:MovieClip;
-
var _loadedSWFs:int;
-
-
-
startLoading(_swfPathArr);
-
-
function startLoading(pathArr:Array):void {
-
_swfLoader = new Loader();
-
_swfRequest = new URLRequest();
-
-
loadSWF(pathArr[0]);
-
}
-
-
function loadSWF(path:String):void {
-
setupListeners(_swfLoader.contentLoaderInfo);
-
-
_swfRequest.url = path;
-
_swfLoader.load(_swfRequest);
-
}
-
-
function setupListeners(dispatcher:IEventDispatcher):void {
-
dispatcher.addEventListener(Event.COMPLETE, onSwfComplete);
-
dispatcher.addEventListener(ProgressEvent.PROGRESS, currentSwfProgress);
-
}
-
-
function currentSwfProgress(event:ProgressEvent):void {
-
var _perc:int = (event.bytesLoaded / event.bytesTotal) * 100;
-
// swfPreloader.percentTF.text = _perc + "%";
-
}
-
-
-
function onSwfComplete(event:Event):void {
-
event.target.removeEventListener(Event.COMPLETE, onSwfComplete);
-
event.target.removeEventListener(ProgressEvent.PROGRESS, currentSwfProgress);
-
-
_swfTempClip = event.target.content;
-
_swfTempClip.customID = _loadedSWFs;
-
_swfClipsArr.push(_swfTempClip);
-
-
if(_loadedSWFs <_swfPathArr.length - 1) {
-
_loadedSWFs++;
-
loadSWF(_swfPathArr[_loadedSWFs]);
-
} else {
-
_swfLoader.unloadAndStop();
-
_swfLoader = null;
-
onCompletePreloading();
-
}
-
}
-
-
function onCompletePreloading():void {
-
contentContainer.addChild(_swfClipsArr[0]);
-
-
news_btn.addEventListener(MouseEvent.CLICK, setContent);
-
portfolio_btn.addEventListener(MouseEvent.CLICK, setContent);
-
contact_btn.addEventListener(MouseEvent.CLICK, setContent);
-
}
-
-
function setContent(event:MouseEvent):void {
-
var _swfToAdd:MovieClip;
-
-
switch(event.target.name) {
-
case "news_btn":
-
_swfToAdd = _swfClipsArr[0];
-
break;
-
-
case "portfolio_btn":
-
_swfToAdd = _swfClipsArr[1];
-
break;
-
-
case "contact_btn":
-
_swfToAdd = _swfClipsArr[2];
-
break;
-
}
-
-
contentContainer.removeChildAt(contentContainer.numChildren-1);
-
contentContainer.addChild(_swfToAdd);
-
trace(_swfToAdd.customID);
-
}
Please feel free to correct me and notice, that this snippet is simplified, e.g. IO_ERRORs must be listened, fallbacks must be defined, etc. I just wanted to keep the focus on loading, storing and adding multiple SWFs.



February 16th, 2010
Marvin Blase
Posted in
Tags:
Hey Marvin, what if I want multiple swfs to play like a presentation (one after the other) and not have a "Click" action? Thanks
hello bubdy, your code is great. I have one question more. if file "00.swf" need to load some files "Image.jpg" more, how to make preloader for all of them, example:
-"00.swf"
-"image01.jpg"
-"image02.jpg"
-"image03.jpg"
-"image04.jpg"
-"01.swf",
-"02.swf
hello bubdy, your code is great. I have one question more. if file "00.swf" need to load some files "Image.jpg" more, how to make preloader for all of them, example:
-"00.swf"
|----"image01.jpg"
|----"image02.jpg"
|----"image03.jpg"
|----"image04.jpg"
-"01.swf",
-"02.swf
Scene 1, Layer 'Layer 1', Frame 1, Line 59 1120: Access of undefined property news_btn.
Scene 1, Layer 'Layer 1', Frame 1, Line 60 1120: Access of undefined property portfolio_btn.
Scene 1, Layer 'Layer 1', Frame 1, Line 61 1120: Access of undefined property contact_btn.
I keep getting this Compiler Error
I have a question. I am using the code and it works great when I run it from my desktop. The problem occurs when I run it online. Only the last swf loaded plays. The others are "paused?"
I have 4 swfs, all are simple with no code. Just an animation that loops. I have my buttons set up to switch the loaded swf.
What happens is that when I click the buttons, the clips switch but only the last clip in the array actually plays. This needs to work on IE 8, and flashplayer 10.3.
Just to test, I switched the order of the swfs in the array and again only the last loaded swf plays so I know it isn't the swfs causing the problem. I suspect it is IE 8.
Hi, as duc asked, it would be really nice to know how to make it work like a presentation one swf after onother, without have mouse events
Thanks ! Very usefull code !
Hi marvin,
Im using Flash CS5 AS3 and it all seems to work ok but how would i use this line of code // swfPreloader.percentTF.text = _perc + "%"; to add a preloader and is this for all swf's? Also how could you tween the swf's being loaded and unloaded?
kind regards
Marcus Olley
...Need your help! I am using Concrete5 CMS and need Flash help.
I am looking to load "multiple" swf [flash] files (as in the image Slideshow) on the header block of the default template (parent page) to show all across on the selected child pages.
- note: FYI - I need multiple swf files, because each has its own animation and I want it to load randomly, not in the same order (otherwise I'd just make one long flash mov).
Now I want to able to load multiple swf files (15-20 files), on the header, like so...
1. Load swf file and play/remain on stage for say... 30 seconds each
2. unload and simultaneously repeat the process
3. must load random swf as if it was an images slideshow.
Any suggestions? Thanks for your help.
//G
its not good please provide another one which is better than this.
Works great! Thanks!