Weitere anschauliche Beispiele zum Thema hier: http://www.java2s.com
Loading Sound siehe diesen Tipp auf neuer Seite
Loading XML siehe diesen Tipp auf neuer Seite
Loading Fonts aus extener SWF- Datei siehe diesen Tipp
Es gibt 3 Möglichkeiten Anzeigenelemente zu laden
Anzeigenlemente sind:
SWF-Dateien, JPG, GIF und PNG- Bilder, außerdem können mit dem [Embed Tag] in Flex SVG- Dateien eingebunden werden.
Um ein Anzeigelement zu laden sind folgende 3 Schritte erforderlich:
var myLoader:Loader = new Loader();
var myUrl:URLRequest = new URLRequest("flash.swf");
myLoader.load(myUrl);
addChild(myLoader);
Der Pfad zum Anzeigenobjekt ist ein String und kann direkt im Konstruktor angegeben werden:
var myUrl:URLRequest = new URLRequest("flash.swf");
Oder über die flash.net.URLRequest Variable url:
var myUrl:URLRequest = new URLRequest();
myUrl.url = "flash.swf";
Jede URLRequest Instanz beschreibt also den Pfad zu einem Element auf dem lokalen Dateisystem oder im Netz. Abhängig vom Betriebssystem sind verschiedene Netzwerk Protokolle möglich. Einige Protokolle werden aus Sicherheitsgründen ohne Vorwarnung geblockt, von daher sollte man bei ungewöhnlichen Protokollen damit rechnen.
Es ist eine relative oder absolute Pfadangabe möglich. Bei relativen Pfadangaben sind einige Besonderheiten zu beachten.
Was bedeutet das in der Praxis:
Wenn eine SWF Datei geladen ist, wird das Actionscript der Klassendatei und das Actionscript des ersten Bildes ausgeführt. Nehmen wir an, wir haben einen Ordner darin liegen
In der film.swf gibt es im ersten Bild eine URLRequest Instanz, welche auf das Bild verweist und die dazugehörigen anderen Aktionen.
var myUrl:URLRequest = new URLRequest("../img/kopf.png");
Im stageOwner.swf gibt es den Ladevorgang und die URLRequest Instanz mit Verweis auf film.swf. Nun passiert folgendes sofern ich die film.swf dirket im Browser oder über den Standalone Player aufrufe wird das Bild geladen. Wenn ich jedoch die stageOwner.swf aufrufe, welche die film.swf läd, müsste die relative Pfadangabe in der film.swf in Bezug zur stageOwner.swf gesetzt werden also:
var myUrl:URLRequest = new URLRequest("img/kopf.png");
Sofern es eine Html-Datei in einem anderen Ordner gibt, in welche die stageOwner.swf eingebettet ist, müssten alle relativen Pfadangaben auf die Html-Datei verweisen.
Actionscript der Klasse AssetLoader.as
package
{
import flash.display.*;
import flash.net.URLRequest;
import flash.events.Event;
public class AssetLoader extends Sprite
{
private var loader:Loader;
public function AssetLoader()
{
loader= new Loader();
var urlRequest:URLRequest=new URLRequest("sunset.jpg");
loader.load(urlRequest);
loader.contentLoaderInfo.addEventListener(Event.INIT, initListener);
}
private function initListener (e:Event){
trace(loader.content.width);
trace(loader.getChildAt(0).height);
trace(e.target.content.height);
addChild(loader.content);
}
}
}
Bevor man auf ein geladenes Element zugreifen kann, muss es von Actionscript initialisiert werden. Hier gibt es Unterschiede zwischen einem Bild und einer SWF-Datei.
Das bedeutet, der Ladevorgang ist unter Umständen noch nicht abgeschlossen. Wenn alles geladen wurde wird das Event.COMPLETE ausgelöst, siehe unten.
Die Instanz einer Loader Klasse kann und darf nur ein Child Element enthalten: das geladene Element. Das kann eine swf-Datei oder ein Bild sein.jpg,gif, png
Man kann erst auf das geladene Element zugreifen wenn der Event.INIT in Kraft tritt. Dieses Ereignis wird auf das LoaderInfo Objekt des geladenen Objekts registriert. Das LoaderInfo Objekt ist ein eigenständiges Objekt, welches Informationen über das geladene Objekt zur Verfügung stellt. Jede Loader Instanz stellt eine Referenz auf das LoaderInfo Objekt des geladenen Objekt bereit und zwar über die Variable contentLoaderInfo
Wie man sieht, kann man auf 3 Arten auf das geladene Element zugreifen:
loader.content
loader.getChildAt(0)
e.target.content
Über die Variable content,
über das einzige Child Element
über den Event Target
Beachte, dass die 3 Trace Befehle (im Beispielcode oben Zeile 25-27) vor der Aktion addChild(loader.content) aufgeführt sind. Denn sobald man mittels addChild(loader.content) das Element einem neuen DisplayObjectContainer hinzufügt, wird es aus dem ursprünglichen Elternteil entfernt.
trace(loader.numChildren); // 1
addChild(loader.content);
trace(loader.numChildren); // 0
Es gibt verschiedene Möglichkeiten die geladenen Inhalte anzusprechen
Hier wird das vorige Beispiel um einige Funktionen erweitert. Im vorigen Beiespiel wird aufgeführt, was benötigt wird. (fla Datei, Bild, Main class)
In diesem Beispiel wir der Ladevorgang überwacht und angezeigt. Dazu wird ein Textfeld erzeugt, in dem die geladenen kbytes angezeigt werden. Der Ereignislistener Event.PROGRESS wird während des Ladevorgangs ausgeführt, Das LoaderInfo Objekt stellt die Informationen über die geladenen bytes und zu ladenden Bytes bereit.
Der Ereignislistener Event.COMPLETE tritt in Kraft, wenn der Ladevorgang abgeschlossen ist. Beachte, dass auch dieses Ereignis auf das LoaderInfo Objekts des Loader Objekts registriert wird. In diesem Beispiel wird nach Abschluss des Ladevorgangs das Textfeld entfernt.
package
{
import flash.display.*;
import flash.net.URLRequest;
import flash.events.*;
import flash.text.*;
public class AssetLoader extends Sprite
{
private var loader:Loader;
private var progressOutput:TextField;
public function AssetLoader()
{
createLoader();
createProgressIndicator();
loadAsset(new URLRequest("sunset.jpg"));
}
private function createLoader():void
{
// Loader erstellen
loader = new Loader();
// events registrieren
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressListener);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeListener);
loader.contentLoaderInfo.addEventListener(Event.INIT, initListener);
}
private function createProgressIndicator():void
{
progressOutput = new TextField();
progressOutput.autoSize=TextFieldAutoSize.LEFT;
progressOutput.border=true;
progressOutput.background=true;
progressOutput.selectable=false;
progressOutput.text="LOADING...";
}
private function loadAsset(urlRequest:URLRequest):void
{
loader.load(urlRequest);
if (! contains(progressOutput)) {
addChild(progressOutput);
}
}
private function progressListener(e:ProgressEvent):void
{
//Update Progress Indicator 1kb is 1024 byte, so devide...
progressOutput.text = "LOADING: "
+Math.floor(e.bytesLoaded/1024)
+"/"+Math.floor(e.bytesTotal / 1024) + " kb";
}
// Listener invoked when the asset has been fully loaded
private function completeListener(e:Event):void
{
// Remove progress indicator.
removeChild(progressOutput);
}
private function initListener(e:Event)
{
addChild(loader.content);
}
}
}
Eines der größten Probleme beim Umstieg von AS2 auf AS3 bereitete mir das Laden von SWF Dateien, denn die Laderei und Entladerei läuft in AS3 etwas anders. So gab es beispielsweise keine entsprechende Funktion zu dem AS2 Befehl unloadMovie(). Es gibt zwar den Befehl loader.unload(), mit dem der Inhalt eines Loaders entladen wird, allerdings werden damit die EventListener oder abspielende Sounds nicht gestoppt. Erst ab Flashplayer 10 gibt es die Funktion unloadAndStop() die explizit für geladene SWF Dateien erstellt wurde,um deren Events zu löschen und somit den Arbeitsspeicher frei zu machen. Siehe dazu: gskinner.com und Adobe Referenzen
var urlAdr:Array = new Array("film1.swf","film2.swf","film3.swf","film4.swf");
var counter:uint = 0;
var ldr:Loader = new Loader();
var requ:URLRequest = new URLRequest(urlAdr[counter]);
ldr.load (requ);
addChild (ldr);
load_btn.addEventListener (MouseEvent.CLICK, loadNext);
function loadNext (evt:MouseEvent):void
{
if (counter < urlAdr.length - 1)
{
counter++;
}
else
{
counter = 0;
}
requ = new URLRequest(urlAdr[counter]);
ldr.unloadAndStop ();
ldr.load (requ);
}
siehe auch Fonts aus extener Bibliothek laden
In diesem Beispiel wird eine SWF- Datei geladen. Anschließend wird in der Parent-swf eine Instanz einer Movieclipklasse aus der Bibliothek der geladenen SWF-Datei erzeugt.
Es gibt eine Fla/ SWF-Datei namens "mcLib.swf". In der Biblithek befindet sich eine Movieclipklasse namens "Ball".
Im gleichen Ordner befindet sich eine Fla/ SWF- Datei namens "loadMc.swf". Diese läd die "mcLib.swf" und erzeugt eine Instanz von "Ball" und fügt sie der Displayliste hinzu.
Es folgt das Actionscript des ersten Bildes der loadMc.swf
import flash.display.MovieClip;
var loader:Loader;
loader= new Loader();
var urlRequest:URLRequest = new URLRequest("mcLib.swf");
loader.load(urlRequest);
loader.contentLoaderInfo.addEventListener( Event.INIT, assetsReady );
function assetsReady( evt:Event ):void
{
var ballRef:Class = evt.target.content.loaderInfo.applicationDomain.getDefinition("Ball");
var ball:MovieClip = MovieClip(new ballRef());
addChild( ball );
}
Weiter oben wurde erklärt, dass Event.INIT ausgelöst wird, wenn der erste Frame geladen ist. Will man Zugriff auf Instanzen bekommen, die in einem höherem Frame der geladenen SWF-Datei liegen, bekommen, "muss" man in einer Timer-Schleife abfragen ob dieses Object vorhanden ist. Es gibt allerdings auch andere Möglichkeiten dieses Problem zu lösen.
Im folgenden Beispiel gibt es eine fla/swf namens "multiFrame.swf" in deren viertem Bild ein Textfeld namens "tFeld" liegt. Im vierten Bild befindet sich die Action stop();
Außerdem gibt es eine fla/ swf namens "loaderMc.swf" welche "multiFrame.swf" läd und abfragt ob "tFeld" vorhanden ist. Ist die Bedingung erfüllt, wird "tFeld" ein Text zugewiesen und "multiFrame.swf" der Displayliste hinzugefügt.
Actionscript von loaderMc.swf
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, initListener);
loader.load(new URLRequest("multiFrame.swf"));
function initListener(evt:Event):void
{
var timer:Timer = new Timer(100,0);
timer.addEventListener(TimerEvent.TIMER, timerListener);
timer.start();
}
function timerListener(evt:TimerEvent):void
{
try
{
//Überprüfen ob tFeld vorhanden ist
if (loader.content.hasOwnProperty("tFeld"))
{
trace(Object(loader.content).tFeld.text);
//Timer stoppen
evt.target.stop();
//Zugriff auf geladenen SWF
var swfRef:* = loader.content;
var clip:MovieClip=swfRef;
addChild(clip);
clip.tFeld.text="Hurra!";
}
}
catch (e:Error)
{
trace("ist noch nicht da");
}
}
In diesen AS3 Player wird ein SWF Film geladen. Man hat einen Ladebalken und eine Abspielsteuerung mit Pause und Stop Taste. Außerdem gibt es einen home-Button, der zurück zum Anfang spult, wo man erneut den Film laden kann. Das Beispiel ist wieder auf das nötigste reduziert. Damit man es versteht und sich entsprechend erweitern kann. Siehe auch meinen Tipp-Sound, für einen Sound-on-off Button. Siehe auch den Tipp flashvars, damit ließe sich dieses Beispiel insofern erweitern, dass man die Film-Urls aus einer Datenbank holt. Siehe auch das Beispiel unter Timeline und Display Objekte, damit lassen sich auch Display Objekte des geladenen Films abspielen und stoppen egal wie tief sie verschachtelt sind.
function showInfo(anzeigeText:String) {
info.text=anzeigeText;
}
//---------------------init-------------------------------
home_btn.visible=false;
ladebalken.visible=false;
var request:URLRequest;
var ldr:Loader;
var percentSetup:int;
var mc:*;
//-----------------------Film laden-------------------
function laden(evt:MouseEvent) {
movi_btn.visible=false;
home_btn.visible=true;
request = new URLRequest("film1.swf");
ldr= new Loader();
addChild(ldr);
setChildIndex(ldr,0);
ldr.load(request);
ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
ldr.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
ldr.contentLoaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgress );
}
//-------------Error, eine Meldung für alles---------------------
function errorHandler( event:IOErrorEvent):void {
showInfo("Der Film konnte nicht geladen werden.");
ldr.close();
}
//----------------------Ladevorgang überwachen-------------------------
function onProgress( event:ProgressEvent ):void {
ladebalken.visible=true;
percentSetup = Math.round(((event.bytesLoaded/event.bytesTotal)*100));
ladebalken.scaleX=percentSetup/100;
showInfo("loading "+percentSetup+"%");
if (event.bytesLoaded==event.bytesTotal) {
showInfo("");
ladebalken.visible=false;
}
}
//---------- Ladevorgang startet----------
function initHandler(evt:Event) {
home_btn.addEventListener(MouseEvent.CLICK, deleteLoader);
play_btn.addEventListener(MouseEvent.CLICK, abspielen);
pause_btn.addEventListener(MouseEvent.CLICK, stoppen);
mc=ldr.content;
//film abspielen
function abspielen(evt:MouseEvent) {
mc.play();
}
//film stoppen
function stoppen(evt:MouseEvent) {
mc.stop();
}
//loader löschen, videowahl einblenden
function deleteLoader(evt:MouseEvent) {
home_btn.visible=false;
movi_btn.visible=true;
mc.stop();
if (percentSetup<100) {
ldr.close();
}
if (stage.contains(ldr)) {
removeChild(ldr);
}
}
}
movi_btn.addEventListener(MouseEvent.CLICK, laden);
Hier habe ich eine Klasse TLoader.as und eine fla (laden5.swf), in der über 2 Buttons 2 swf Filme geladen werden. Über den Play und Stop Button kann man die Hauptzeitleiste des geladenen Films steuern. Man kann sich hierbei schnell mal vertun, wenn man damit versucht Filme zu stoppen, deren Animation innerhalb einer MC-Instanz ist oder deren Bewegung programmiert wurde. Auf der Actionscript 3 Seite meiner Tipps findet ihr ein Beispiel, wie man alle Zeitleisten eines geladenen SWF Films stoppen und abspielen kann. Auch wenn Sie mehrmals verschachtelt sind.
Wenn man einen Film lädt der Sound abspielt und dann den Film durch einen andere ersetzt, läuft trotzdem der Sound weiter. Das liegt daran, dass der Sound kein DisplayObject ist und somit nicht automatisch entfernt wird. Der Sound muss also explizit angesprochen werden. Wie man ihn stoppt, könnt ihr in meinem Beispiel sehen.
Actionscript der laden5.swf
var film:TLoader = new TLoader();
addChild(film);
function starten1(evt:MouseEvent):void {
film.loadSwf="film1.swf";
}
function starten2(evt:MouseEvent):void {
film.loadSwf="film4.swf";
}
function stopFilm(evt:MouseEvent):void {
film.stopFilm();
}
function playFilm(evt:MouseEvent):void {
film.playFilm();
}
movi1_btn.addEventListener(MouseEvent.MOUSE_UP, starten1);
movi2_btn.addEventListener(MouseEvent.MOUSE_UP, starten2);
stop_btn.addEventListener(MouseEvent.MOUSE_UP, stopFilm);
play_btn.addEventListener(MouseEvent.MOUSE_UP, playFilm);
Actionscript der Klasse TLoader.as
package {
import flash.display.*;
import flash.net.URLRequest;
import flash.events.*;
import flash.media.SoundMixer;
public class TLoader extends Sprite {
private var lader:Loader = new Loader();
private var request:URLRequest;
private var clip:MovieClip;
public function TLoader() {
}
public function set loadSwf(swfUrl:String):void {
SoundMixer.stopAll();
request=new URLRequest(swfUrl);
lader.load(request);
addChild(lader);
lader.contentLoaderInfo.addEventListener(Event.INIT,laderInhalt);
}
private function laderInhalt(event:Event):void {
var movie:* =lader.content;
this.clip=movie;
}
public function playFilm():void {
this.clip.play();
}
public function stopFilm():void {
this.clip.stop();
}
}
}
Achtung!!! Wenn Html-Datei und SWF-Film in verschiedenen Verzeichnissen liegen, gilt bei relativen Pfadangaben (filmURL) die Html-Datei und nicht der SWF-Film als oberste Ebene.
Actions der Klassendatei SwfLader.as
Siehe hierzu das Beispiel weiter oben auf der Seite, dort werden Schritt für Schritt die Funktionen erklärt. In dieser Klassendatei befinden sich 2 public functions, die den Film ab Bild 1 abspielen playStart() und den Film stoppen stopFilm();
package {
import flash.display.*;
import flash.net.URLRequest;
import flash.events.*;
public class SwfLader extends Sprite {
private var lader:Loader;
private var clip:MovieClip;
public function SwfLader(urlString:String) {
var request:URLRequest = new URLRequest(urlString);
lader = new Loader();
lader.load(request);
addChild(lader);
lader.contentLoaderInfo.addEventListener( Event.INIT, laderInhalt );
}
private function laderInhalt( event:Event ):void {
var movie:* = lader.content;
this.clip=movie;
}
public function playStart():void {
this.clip.gotoAndPlay(1);
}
public function stopFilm():void {
this.clip.stop();
}
}
}
siehe auch meinen XML Tipp
Hier werden nacheinander mehrere Bilder geladen. Die URLs der Bilder werden in einem Array aufgeführt, könnten aber auch genausogut aus einer geladenen XML Datei stammen. Es gibt eine Textmeldung über den Ladevorgang. Nachdem das erste Bild geladen ist und zur Anzeige gebracht wird, wird das nächste Bild geladen. Beachte auch die hier vorgestellte Methode bitmapData.clone(). Die geladenen Pixel werden automatisch in ein BitmapData Objekt platziert. Mit der clone() Methode werden die Pixeldaten im Konstruktor eines neuen Bitmap Objekts übertragen.
Das folgende Actionscript steht im ersten Frame einer fla Datei.
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.text.TextField;
import flash.net.URLRequest;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
var bilder:Array = new Array("img/img1.jpg","img/img2.jpg","img/img3.jpg","img/img4.jpg");
var loader:Loader;
var index:uint=0;
var progressOutput:TextField;
createLoader();
createProgressIndicator();
load(new URLRequest(bilder[index]));
function createLoader():void
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressListener);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeListener);
loader.contentLoaderInfo.addEventListener(Event.INIT, initListener);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);
}
function createProgressIndicator():void
{
progressOutput = new TextField();
progressOutput.autoSize = TextFieldAutoSize.LEFT;
progressOutput.border = true;
progressOutput.selectable = false;
progressOutput.x = 20;
progressOutput.y = 140;
progressOutput.text = "Läuft...";
}
function load(urlRequest:URLRequest):void
{
loader.load(urlRequest);
if (! contains(progressOutput))
{
addChild(progressOutput);
}
}
function progressListener(evt:ProgressEvent):void
{
progressOutput.text = "Läuft..." + Math.floor(evt.bytesLoaded / 1024) + " / " + Math.floor(evt.bytesTotal / 1024) + " kb";
}
function initListener(evt:Event):void
{
//evt.target.content ist das Objekt welches das geladene bitmap repraesentiert
var newImage:Bitmap = new Bitmap(evt.target.content.bitmapData.clone());
newImage.x= 120 *index;
addChild(newImage);
}
function completeListener(evt:Event):void
{
removeChild(progressOutput);
if(index < bilder.length-1){
index++;
load(new URLRequest(bilder[index]));
}
}
function ioErrorListener (evt:IOErrorEvent):void{
progressOutput.text = "Loading Error / Fehler beim Laden";
}