12.2 Reihenfolge der Ereignisse
Reihenfolge testen
Da die Reihenfolge der Ereignisabarbeitung von Macromedia nicht dokumentiert ist, kann es leider auch zu Änderungen dieser kommen! Ein regelmäßiger Test ist darum unerlässlich.
Der Nachrichtenfluss, also die Reihenfolge, in der Flash die Ereignisse abarbeitet, ist von zentraler Bedeutung. Denn nicht selten entstehen Fehler dadurch, dass Flash einzelne Anweisungen zu früh, zu spät oder gar nicht ausführt.
Schritte der bildbasierten Ereignisbearbeitung
12.2.1 Bildbasierte Ereignisreihenfolge
Die bildbasierte Ereignisabarbeitung erfolgt im Wesentlichen in den folgenden Schritten, wie in Abbildung 12.1 gezeigt:
1. |
Bei der bildbasierten und durch die Abspielgeschwindigkeit vorgegebenen Abarbeitung der Anweisungen beginnt Flash vor der Darstellung des Bildes mit den bereits vorhandenen Movieclips (dies macht erst nach dem ersten Bildwechsel in einer Anwendung Sinn) und sendet diesen die Nachricht onEnterFrame. |
|
|
2. |
Erst dann geht es an die in den Schlüsselbildern platzierten Skripte, die von oben nach unten abgearbeitet werden (Bildskripte); so als ob alle Anweisungen in nur einem Schlüsselbild hintereinander weg aufgeführt wären. |
|
|
Hier klicken, um das Bild zu Vergrößern
Abbildung 12.1
Bildbasierte Ereignisreihenfolge
3. |
Jetzt startet Flash mit der Darstellung von hinten nach vorne (bzw. von unten nach oben)! |
|
|
4. |
Noch bevor die in der Anwendung enthaltenen Movieclips angezeigt werden, führt Flash die Anweisungen in der Ereignisprozedur onLoad gefolgt von den Anweisungen in den Ereignismethoden onLoad aus – wie bereits erwähnt, beginnt Flash dabei mit dem hintersten Element. |
|
|
5. |
Und noch bevor es zum nächsten Movieclip geht, arbeitet Flash die Inhalte des Movieclips ab. Flash beginnt also für jeden Movieclip wieder von vorne und schaut, ob bereits Movieclips enthalten sind, arbeitet dann die Bildskripte ab usw. |
|
|
6. |
Erst dann geht es zum naechsten Movieclip, und anschliessend erfolgt wieder ein Bildwechsel. |
|
|
Etwas verwirrend ist, dass Flash bei Ereignissen wie onEnterFrame und onMouse-
Up in der Reihenfolge genau andersherum agiert und die Movieclips, die weiter oben liegen, bevorzugt abarbeitet.
12.2.2 Bildunabhängige Ereignisreihenfolge
Hier klicken, um das Bild zu Vergrößern
Abbildung 12.2
Bildunabhängige Ereignisreihenfolge
Flash arbeitet immer zuerst alle Ereignisprozeduren gefolgt von den Ereignismethoden ab. Je nach Ereignis beginnt Flash mit den hintersten (onLoad) oder mit den vordersten Objekten. Erst dann kommen die Listener an die Reihe. Die Abarbeitungsreihenfolge bei den Listenern entspricht momentan der Anmeldereihenfolge. Die zuerst angemeldeten Objekte behandelt ActionScript dabei zuerst. Dafür gibt es aber keine Garantie, und Macromedia könnte dieses Verhalten somit jederzeit wieder ändern.
Um auf die Ereignisse und die Ereignishierarchie weitergehenden Einfluss zu nehmen, verwenden Sie die im Folgenden vorgestellten Anweisungen updateAfterEvent, setInterval und initClip oder die Endung _changed in einer Bildbezeichnung.
12.2.3 updateAfterEvent
Die seit Flash 5 verfügbare Funktion updateAfterEvent(); ist die einzige Möglichkeit in Flash, die Darstellung auf der Bühne unabhängig von der eingestellten Bildrate zu beeinflussen.
Dies macht nur bei Anweisungen Sinn, die unabhängig von der Abspielgeschwindigkeit ausgelöst werden, wie z.B. bei Benutzerinteraktionen. Anders als in der Dokumentation beschrieben funktioniert die Anweisung mit Ereignisprozeduren, Ereignismethoden, Listenern und setInterval. Bei den Ereignisprozeduren und Ereignismethoden beschränkt sich diese Anweisung jedoch auf die Movieclip-Ereignisse (onClipEvent).
Im folgenden Beispiel dreht sich ein »selbst definierter Mauszeiger« (mcMouse) immer in Richtung eines anderen Movieclips (mcMitte). Dies geschieht unabhängig von der eingestellten Bildrate (das Beispiel auf der CD-ROM besitzt eine Bildrate von 0,1 Bild pro Sekunde, bzw. es wird nur alle zehn Sekunden ein Bildwechsel durchgeführt):
mcMouse.onMouseMove = function() {
updateAfter Event.fla
// Bestimme Winkel bzgl. Mitte
this.rad = Math.atan2(_root.mcMitte._y-this._y, _root.mcMitte._x-this._x);
this._rotation = this.rad/(Math.PI/180)-270;
// Positioniere auf dem Mauszeiger
this._x = _root._xmouse;
this._y = _root._ymouse;
// Zeige unabhängig von der Bildrate
updateAfterEvent();
};
12.2.4 setInterval
setInterval ermöglicht Ihnen den regelmäßigen und zeitgesteuerten Aufruf von Funktionen und Methoden. Sie legen eine Zeitdauer in Millisekunden fest, in der eine Funktion oder eine Methode aufgerufen werden soll. ActionScript wiederholt diesen Aufruf in dem von Ihnen festgelegten Intervall so lange, bis Sie das Intervall mit clearInterval wieder löschen.
Da die Intervallangabe in Millisekunden erfolgt, findet die Abarbeitung im Zusammenspiel mit updateAfterEvent(); unabhängig von der Bildrate statt. Um genau zu sein: updateAfterEvent(); hilft nur bei einer Intervallfolge, die schneller als die Bildrate ist. Wenn Sie z.B. eine Bildrate von einem Bild pro Sekunde haben, also jedes Bild genau 1000 Millisekunden angezeigt wird, dann wird ein Intervall mit einer kürzeren Dauer von z.B. 100 Millisekunden entsprechend zehnmal pro Bild aufgerufen, was bei updateAfterEvent(); auch zu einer Veränderung der Darstellung führen kann. Bei dieser Vorgehensweise kam es beim Test jedoch in den meisten Fällen zu einer massiven Verlangsamung der Darstellung.
// Lege Intervall mit anonymer Funktion als Parameter fest
setInterval(function () {_root.mcKuh._x++;
updateAfterEvent();}, 50);
Sollte ein Intervall länger dauern als die Darstellung eines Bildes, dann führt Flash die zugehörigen Anweisungen ähnlich einem onEnterFrame beim nächsten Eintritt in ein Bild aus, so dass updateAfterEvent(); nicht benötigt wird.
Arten der Anwendung
Die Anwendung von setInterval erfolgt auf zwei unterschiedliche Arten: entweder mit einer Funktion oder mit einem Objekt und einer zugehörigen Methode als Parameter. Im folgenden Beispiel wird alle zwei Sekunden eine Funktion aufgerufen:
werdeWahnsinnig = function () {
setInterval.fla
mcKuh.gotoAndPlay("wahnsinnig");
};
// id ist die Kennung des Intervalls für clearInterval
id = setInterval(werdeWahnsinnig, 2000);
Um Parameter an die Funktion durchzureichen, verwenden Sie die folgende Schreibweise:
werdeWahnsinnig = function (obj, bild) {
mcKuh.gotoAndPlay(bild);
};
id = setInterval(werdeWahnsinnig, 2000, mcKuh,"wahnsinnig" );
alternative Schreibweise
Anstelle der Funktionsschreibweise sieht eine vergleichbare Schreibweise mit einem Objekt, einer Methode und mit einem angehängten Parameter wie folgt aus:
id = setInterval(mcKuh, "gotoAndPlay", 2000 ,"wahnsinnig" );
Es ist Zufall, dass es sich bei dem Objekt im letzten Beispiel um einen Movieclip und eine bereits vordefinierte Methode handelt. Genauso gut hätten hier auch ein selbst definiertes Objekt und eine dazu passende Methode stehen können.
Löschen
Das Löschen eines Intervalls geschieht über dessen ID, die von setInterval zurückgegeben wird. Diese ID geben Sie als Parameter von clearInterval an:
id = setInterval(mcKuh, "gotoAndPlay", 500 ,"wahnsinnig" );
// Löschen eines Intervalls bei Klick
mcKuh.onRelease=function () {
clearInterval(_root.id);
}
Im Test zeigte sich übrigens, dass Flash die Intervalle einfach nur durchzunummerieren scheint: Die Angabe der Zahl 1 bei clearInterval reicht ebenfalls aus, um das zuerst definierte Intervall zu löschen.
12.2.5 initClip
Die Anweisung #initclip wird normalerweise im Zusammenspiel mit Komponenten verwendet, um Initialisierungsanweisungen durchzuführen (siehe Kapitel 17, »Komponenten«). Aber auch ohne Komponenten kann der Einsatz vom #initclip hilfreich sein, um die Initialisierung von Movieclips zu steuern.
Da diese Anweisung nur im ersten Schlüsselbild eines Movieclips zulässig ist, gibt Flash in allen anderen Fällen die folgende oder eine ähnliche Meldung aus: »Szene=Szene 1, Ebene=actionscript, Bild=1: Zeile 1: #initclip/#endinitclip nur zulässig bei Bild 1 der Movieclip-Symbole.«
Außerdem wird jeder durch #initclip und #endinitclip eingerahmte Block nur genau einmal ausgeführt. Handelt es sich um ein exportiertes Symbol, dann führt Flash die Aktionen unmittelbar vor dem ersten Bild aus. Sonst kommen die Initialisierungsanweisungen ins Spiel, sobald das Symbol zum ersten Mal verwendet wird. In diesem Fall werden die Anweisungen unmittelbar vor den Bildaktionen ausgeführt.
Das folgende Skript initialisiert eine Klasse (Kuh), welche die Fähigkeiten und Eigenschaften von der Movieclip-Klasse erbt sowie mit einem Symbol (Kuhsymbol) verbunden ist. Dies führt dazu, dass jede Instanz dieses Symbols die neu programmierten Fähigkeiten erhält, ohne dass sich das auf andere Movieclips auswirkt:
#initclip
mit Clip.fla
function Kuh () {
super();
}
Kuh.prototype=new MovieClip();
Kuh.prototype.werdeWahnsinnig=function () {
this.gotoAndStop("wahnsinnig");
}
Kuh.prototype.onLoad=function () {
this.stop();
}
Kuh.prototype.onPress=function () {
this.werdeWahnsinnig();
}
Object.registerClass("kuhsymbol", Kuh);
#endinitclip
Bei mehreren Initialisierungsblöcken reicht die Angabe einer Zahl in der Form #initclip 5, um die genaue Reihenfolge zu bestimmen.
Sollte Ihnen das an dieser Stelle zu schnell gegangen sein, dann empfehle ich Ihnen einen Blick in das Kapitel »Komponenten« (siehe Seite 426) und das Studium des Kapitels »Movieclips« mit der Erklärung der Anweisung Object.registerClass (siehe Seite 362).
12.2.6 _changed
_changed
Wenn der Benutzer ein Textfeld ändert, können gezielt Aktionen ausgeführt werden. Alles, was man dafür seit Flash 5 braucht, ist ein Textfeld, das mit einer Variablen verbunden ist, und ein Schlüsselbild in derselben Zeitleiste mit der Bildbezeichnung variablenname_changed. Das Entscheidende ist die Zeichenkette _changed direkt hinter dem Variablennamen des Textfeldes in der Bildbezeichnung. Alle Aktionen, die in diesem Bild liegen, werden ausgeführt, sobald ein Anwender den Inhalt des Textfeldes verändert. In unseren Tests erwies sich diese undokumentierte Funktion aber zu Recht als undokumentiert: Zahlreiche Abstürze verhinderten allzu oft den Einsatz. Verwenden Sie stattdessen die Ereignismethode oder den Listener namens onChanged.
|