Recipe 6.6.
Loading External Images at Runtime
Problem
You
want to load an external
image into a movie while it plays.
Solution
Use the new Loader class to load an image
(.jpg, progressive .jpg, .png, or .gif) and display it
on-screen.
Discussion
Recipe
9.17 demonstrates how to embed external assets into a movie at
compile time via the [Embed] metadata tag. To load
external images or movies at runtime during the playback of a
.swf, the Loader class needs to be used.
The flash.display.Loader class is
very similar to the
flash.net.URLLoader class discussed in Recipe
19.3. One of the key differences is that Loader
instances are able to load external images and movies and display
them on-screen, whereas URLLoader instances are useful
for transferring data.
There are three fundamental steps for loading
external content:
-
Create an instance of the Loader
class.
-
Add the Loader instance to the display
list.
-
Call the
load( ) method to pull in an external asset.
The load( ) method of the Loader
class is responsible for downloading the image or .swf file.
It takes a single URLRequest object as a parameter that
specifies the URL of the asset to download and display.
The following is a small example of using a
Loader instance to download an image named image.jpg
at runtime. The code in the LoaderExample constructor has
been commented to coincide with the three basic loading steps
previously outlined:
package {
import flash.display.*;
import flash.net.URLRequest;
public class LoaderExample extends Sprite {
public function LoaderExample( ) {
// 1. Create an instance of the Loader class
var loader:Loader = new Loader( );
// 2. Add the Loader instance to the display list
addChild( loader );
// 3. Call the load( ) method to pull in an external asset
loader.load( new URLRequest( "image.jpg" ) );
}
}
}
When running this code, the Flash Player looks
for image.jpg in the same directory that the .swf
movie is being served from because the URLRequest object
uses a relative URL. Either a relative or absolute URL can be used
to point to the location of the target to load, but the actual
loading of the asset is governed by Flash Player's security
sandbox, as discussed in Recipe
3.12. As soon as the asset has downloaded, it is automatically
added as a child of the Loader instance.
When loading external assets, it's possible that
something could go wrong during the loading process. For instance,
perhaps the URL is pointing to the incorrect location due to a
spelling mistake, or there's a security sandbox violation that
won't allow the asset to be loaded. Or, it's possible that the
asset is large and is going to take a long time download. Rather
than just having an empty screen while the asset downloads, you'd
like to show a preloader to inform the user of the download
progress.
In these situations, you should add event
listeners to the contentLoaderInfo property of the
Loader instance to be able to respond to the different
events as they occur. The contentLoaderInfo property is an
instance of the flash.display.LoaderInfo class, designed to
provide information about the target being loaded. The following is
a list of useful events dispatched by instances of the
LoaderInfo class and what those events mean:
open
-
Generated when the asset has started
downloading.
progress
-
Generated when progress has been made while
downloading the asset.
complete
-
Generated when the asset has finished
downloading.
init
-
Generated when the properties and methods of a
loaded external .swf are available.
httpStatus
-
Generated when the status code for a failed HTTP
request is detected when attempting to load the asset.
ioError
-
Generated when a fatal error occurs that results
in an aborted download, such as not being able to find the
asset.
securityError
-
Generated when data you're trying to load
resides outside of the security sandbox.
unload
-
Generated when either the unload( )
method is called to remove the loaded content or the load( )
method is called again to replace content that already has been
loaded.
The following example demonstrates listening for
the various download progress related events when loading an
image:
package {
import flash.display.*;
import flash.text.*;
import flash.net.URLRequest;
import flash.events.*;
public class LoaderExample extends Sprite {
public function LoaderExample( ) {
// Create the loader and add it to the display list
var loader:Loader = new Loader( );
addChild( loader );
// Add the event handlers to check for progress
loader.contentLoaderInfo.addEventListener( Event.OPEN, handleOpen );
loader.contentLoaderInfo.addEventListener( ProgressEvent.PROGRESS, handleProgress );
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, handleComplete );
// Load in the external image
loader.load( new URLRequest( "image.jpg" ) );
}
private function handleOpen( event:Event ):void {
trace( "open" );
}
private function handleProgress( event:ProgressEvent ):void {
var percent:Number = event.bytesLoaded / event.bytesTotal * 100;
trace( "progress, percent = " + percent );
}
private function handleComplete( event:Event ):void {
trace( "complete" );
}
}
}
When running the preceding code, you'll see the
open message appear in the console window followed by one or more
progress messages displaying the current percent loaded, followed
by the complete message signaling that the download finished
successfully.
By placing code in the event handlers for these
events, you can show the progress of a download as it's being
loaded. For instance, the handleOpen( ) method would be in
charge of creating the preloader and adding it to the display list.
The handleProgress(
) method would update the percentage value of the preloader,
such as setting the text of a TextField instance to the percent
value. Finally, the handleComplete( ) method would
perform "clean up" and remove the preloader, since the asset is
fully downloaded. Focusing on those methods, the code might look
something like this:
private function handleOpen( event:Event ):void {
// Create a simple text-based preloader and add it to the
// display list
_loaderStatus = new TextField( );
addChild( loaderStatus );
_loaderStatus.text = "Loading: 0%";
}
private function handleProgress( event:ProgressEvent ):void {
// Update the loading % to inform the user of progress
var percent:Number = event.bytesLoaded / event.bytesTotal * 100;
_loaderStatus.text = "Loading: " + percent + "%";
}
private function handleComplete( event:Event ):void {
// Clean up - preloader is no longer necessary
removeChild( loaderStatus );
_loaderStatus = null;
}
The preceding code snippet assumes that there is
a _loaderStatus variable as part of the class, with type
TextField:
private var _loaderStatus:TextField;
Instead of messages appearing via the
trace( ) statement as
before, modifying the event handlers allows the loading information
to be presented inside of the movie itself. This allows users to
see the information directly and provides a better experience when
loading large external assets.
See Also
Recipes 3.12,
6.7,
9.17,
and 19.3
|