Der Flash-Player sendet bei jedem Auftreten eines Mausereignisses MouseEvent-Objekte in den Ereignisablauf. Ein Mausereignis wird im Allgemeinen durch ein Benutzereingabegerät wie z. B. eine Maus oder ein Trackball erzeugt, das einen Zeiger verwendet.
Übersicht über mögliche Mausereignisse,
die über InteractiveObject-Instanzen (Sprites, MovieClips, Stage, Loader, SimpleButton, TextField) ausgelöst werden können.
Weitere Information zur Klasse InteractiveObject.
Ereignis | Beschreibung |
mouseDown | Wird ausgelöst, wenn im Flash Player-Fenster die Taste des Zeigegeräts über einer InteractiveObject-Instanz gedrückt wird. |
mouseUp | Wird ausgelöst, wenn im Flash Player-Fenster die Taste des Zeigegeräts über einer InteractiveObject-Instanz losgelassen wird. |
click | Wird ausgelöst, wenn man die Haupttaste des Zeigegeräts über derselben InteractiveObject-Instanz drückt und wieder loslässt. |
doubleClick | Wird ausgelöst, wenn man die Haupttaste des Zeigegeräts zweimal schnell hintereinander über derselben InteractiveObject-Instanz drückt und die doubleClickEnabled-Eigenschaft der Instanz auf true gesetzt ist. |
mouseMove | Wird ausgelöst, wenn man das Zeigegerät bewegt, während es sich auf einer InteractiveObject-Instanz befindet. |
mouseOver | Wird ausgelöst, wenn das Zeigegerät im Flash Player-Fenster über eine InteractiveObject-Instanz bewegt wird. |
mouseOut | Wird ausgelöst, wenn man das Zeigegerät aus einer
InteractiveObject-Instanz herausbewegt. |
rollOver | Wird ausgelöst, wenn man das Zeigegerät auf eine
InteractiveObject-Instanz bewegt. Der Zweck des rollOver-Ereignisses besteht darin, die Programmierung von RollOver-Verhaltensweisen für Anzeigeobjekt-Container mit untergeordneten Objekten zu vereinfachen. RollOver bezieht sich auf den ganzen Container. Dieses Verhalten unterscheidet sich vom mouseOver-Ereignis, das auch immer dann ausgelöst wird, wenn sich die Maus bereits über einem Unterobjekt des Containers befunden hat und von dort direkt in ein anderes Unterobjekt hinein bewegt wird. (Zum Unterschied siehe Video weiter unten.) |
rollOut | Wird ausgelöst, wenn man das Zeigegerät aus einer
InteractiveObject-Instanz herausbewegt. RollOut bezieht sich wieder auf den gesamten Container. Im Gegensatz zum mouseOut-Ereignis, das auch ausgelöst wird, wenn der Zeiger aus einem Unterobjekt des Container herausbewegt wird und direkt in ein nächstes Unterobjekt des Containers wechselt. (Zum Unterschied siehe Video weiter unten.) |
mouseWheel | Wird ausgelöst, wenn ein Mausrad im Flash Player-Fenster über einer InteractiveObject-Instanz betätigt wird. |
Die erzeugten MouseEvent-Objekte enthalten als Eigenschaft den Typ des Mausereignisses. In der nachfolgenden Übersicht sind die möglichen Mausereignistypen gelb hinterlegt.
Wenn während des Mausereignisses die ALT-, STRG- oder SHIFT-Taste gedrückt wurde, kann man das über die MouseEvent-Eigenschaften altKey, ctrlKey und shiftKey abfragen.
Über die Eigenschaft buttonDown kann man feststellen ob die primäre Maustaste (in der Regel die linke Maustaste) gedrückt wurde.
Die Eigenschaften stageX und stageY liefern die x- und y-Koordinate des Mauszeigers zum Zeitpunkt des Ereignisses relativ zum Bühnenursprung und
localX und localY relativ zum Ursprung der umgebenden Sprite-Instanz, in der der Mauszeiger zum Zeitpunkt des Ereignisses war.
Ein Video zum Unterschied von mouseOver und rollOver bzw. mouseOut und rollOut
Mausereignis-Objekte vom Typ ROLL_OVER und ROLL_OUT haben keine Aufstiegsphase.
Alle anderen Mausereignisse haben sowohl eine Empfangs- als auch eine
Aufstiegsphase. Weitere Informationen zum Ereignislauf.
Quellcode in der beigefügten zip-Datei:
mouseOverOut_rollOverOut.fla
Objekte durch Mausklick auf der Bühne erzeugen
Wenn Sie in der nachstehenden swf-Datei mit der Maus an einer beliebigen Stelle klicken, wird ein gelber Stern erzeugt.
Dazu liegt in der Bibliothek ein Movieclip GelberStern für den die Option Export für ActionScript aktiviert ist.
Im ersten Frame des Mainmovies ist folgendes Skript platziert:
this.stage.addEventListener(MouseEvent.MOUSE_DOWN,erzeugeStern);
function erzeugeStern(e:MouseEvent):void {
var stern:MovieClip = new GelberStern();
this.addChild(stern);
stern.x = e.stageX;
stern.y = e.stageY;
}
Erläuterungen zum Script:
Die Bühne this.stage registriert sich mit dem Eventlistener erzeugeStern beim Mausereignis MOUSE_DOWN.
this.stage.addEventListener(MouseEvent.MOUSE_DOWN,erzeugeStern);
Jedesmal, wenn der Eventlistener erzeugeStern durch einen Mausklick auf der Bühne aufgerufen wird, wird eine neue Instanz des Movieclips GelberStern erstellt, in der Variablen stern gespeichert und der Displayliste der Maintimeline (wird über this angesprochen) hinzugefügt.
var stern:MovieClip = new GelberStern();
Abschließend wird der Stern genau an der Stelle des Mausklicks platziert. Die Eigenschaften stageX und stageY des MouseEvents e liefern die Koordinaten des Mauszeigers zum Zeitpunkt des Ereignisses (siehe auch voriges Kapitel). Die Variable stern kann auch vom Typ Sprite sein.
stern.x = e.stageX;
stern.y = e.stageY;
Problem:
Beim Testen dieses Beispiels werden Sie festgestellt haben, dass auch ein Stern erzeugt wird, wenn man einen bereits erzeugten Stern anklickt.
Wenn man nun möchte, dass nur bei einem "echten" Klick auf den blauen Hintergrund ein neuer Stern erzeugt wird, muss man den Ereugnislauf des MOUSE_DOWN-Ereignisses beachten und target bzw. currentTarget unterscheiden (siehe vertiefende Information zu den Eventphasen).
Klickt man auf einen Stern, so ist dieser das Zielobjekt (target). Da der Stern ibeim MOUSE_DOWN-Ereignis nicht registriert ist. wird in der Zielphase kein Eventlistener ausgeführt. In der anschließenden Aufstiegsphase gelangt das Ereignis zur Bühne (currentTarget), und es wird der Eventlistener der Bühne ausgeführt und ein Stern erzeugt.
Nur wenn target und currentTarget identisch sind, hat man wirklich auf die freie blaue Bühnenfläche geklickt.
Man muss daher im Eventlistener durch eine if-Anweisung diese Gleichheit abfragen.
function erzeugeStern(e:MouseEvent):void {
if (e.target == e.currentTarget) {
var stern:MovieClip = new GelberStern();
this.addChild(stern);
stern.x = e.stageX;
stern.y = e.stageY;
}
}
Zum besseren Verständnis können Sie nachfolgende trace-Anweisung in den Eventlistener vor der if-Anweisung einfügen.
trace("target: " + e.target + " currentTarget: " + e.currentTarget);
Abschließend zum Ausprobieren die veränderte swf-Datei:
Quellcode in der beigefügten zip-Datei:
createObjectsClick.fla
createObjectsClick1.fla
Erzeugte Objekte bei gedrückter Maustaste verschieben
Nachdem die Sterne durch Mausklick erzeugt wurden, sollen sie bei gedrückter linker Maustaste auf der Bühne verschoben werden können.
Zum Ausprobieren: Zuerst durch Klick einen Stern erzeugen, dann Stern anklicken und mit gedrückter Maustaste verschieben.
1. Möglichkeit: das Skript wird in der Movieclip-Timeline platziert
Da das für jeden erzeugten Stern möglich sein soll, wird das Skript nicht im Mainmovie in der Maintimeline sondern im ersten Frame der Timeline des Movieclips GelberStern platziert. Damit gilt das Skript für jede Movieclipinstanz des Sterns.
Wichtig!
Im nachfolgenden Skript ist daher mit this der MovieClip GelberStern gemeint, da das Skript in der Timeline des Movieclips liegt.
this.addEventListener(MouseEvent.MOUSE_DOWN, startZiehen);
function startZiehen(e:MouseEvent):void {
this.startDrag(false);
}
this.addEventListener(MouseEvent.MOUSE_UP, stopZiehen);
function stopZiehen(e:MouseEvent):void {
this.stopDrag();
}
Der Movieclip this registriert sich mit dem Eventlistener startZiehen beim Mausereignis MOUSE_DOWN und
beim Mausereignis MOUSE_UP mit dem Eventlistener stopZiehen.
Der Eventlistener startZiehen führt die Sprite-Methode startDrag aus, die es ermöglicht, das angegebene Sprite mit einer Ziehoperation zu verschieben. Das Sprite bleibt so lange ziehbar, bis die Freigabe durch einen Aufruf der stopDrag-Methode aufgehoben wird oder bis ein anderes Sprite als ziehbares Objekt definiert wird. Es kann jeweils nur ein Sprite ziehbar sein.
this.startDrag(false); //oder: e.target.startDrag(false);
Beim Loslassen der Maustaste wird durch den Eventlistener stopZiehen die Möglichkeit, den Stern zu verschieben, wieder aufgehoben indem die Methode stopDrag aufgerufen wird.
this.stopDrag(); //oder: e.target.stopDrag();
Erhält startDrag() als ersten Parameter den Wert true, so wird der Ursprung des Sprites auf den Mauszeiger ausgerichjtet. Das bewirkt in der Regel, dass das Objekt beim Anklicken verschoben wird. Wenn dieser Parameter false ist, bleibt der Mauszeiger beim Verschieben auf dem Anklickpunkt. Das Video zeigt den Unterschied.
Zu startDrag und stopDrag siehe auch ActionScript3: Cursor aus-/einblenden, ändern, animieren und Movieclips an die Maus binden
2. Möglichkeit: das Skript wird in der Maintimeline platziert
Wenn auf der Bühne außer den Sternen auch andere Movieclips platziert sind und jeder Movieclip bei gedrückter Maustaste verschiebbar sein soll, dann ist es besser das Skript in der Maintimeline zu schreibe.
Dazu registriert sich die Maintimeline this mit dem Eventlistener startZiehen beim Mausereignis MOUSE_DOWN und
beim Mausereignis MOUSE_UP mit dem Eventlistener stopZiehen.
Wichtig!
Im nachfolgenden Skript ist mit this das Mainmovie gemeint, da das Skript in der Maintimeline liegt.
this.addEventListener(MouseEvent.MOUSE_DOWN, startZiehen);
function startZiehen(e:MouseEvent):void {
e.target.startDrag(false);
}
this.addEventListener(MouseEvent.MOUSE_UP, stopZiehen);
function stopZiehen(e:MouseEvent):void {
e.target.stopDrag();
}
Wenn ein Movieclip (target) angeklickt wird, dann erreicht das MOUSE_DOWN-Ereignis in der Aufstiegsphase auch die Maintimeline, und es wird der Eventlistener ausgeführt. In der Eventlistenerfunktion wird für das Zielobjekt e.target die Methode startDrag aufgerufen.
Analog gilt das für das MOUSE_UP-Ereignis. Vertiefende Informationen zu den Ereignisphasen
Quellcode in der beigefügten zip-Datei:
createObjectsClickDrag.fla
createObjectsClickDrag1.fla
Drag and Drop - Überschneidung von Objekten prüfen
Bei drag and drop wird ein Objekt angeklickt, mit gedrückter Maustaste verschoben und beim Loslassen der Maustaste über einem Zielobjekt oder Zielbereich platziert. Häufig "rastet" das Objekt beim Verschieben oder Loslassen der Maustaste an einer definierten Stelle des Zielobjekts ein ("magnetischer" Effekt).
Zum Ausprobieren: Klicken Sie in die dunkelblaue Fläche und erzeugen einen gelben Stern. Anschließend ziehen Sie den Stern bei gedrückter Maustaste über den hellblauen Kreis. Beim Loslassen der Maustaste wird der Stern exakt im Zentrum des blauen Kreis platziert.
Beim Loslassen der Maustaste wird immer geprüft, ob das verschobene Objekt das Zielobjekt schneidet bzw. ganz drinnen liegt.
Ganz allgemein gesprochen, geht es darum festzustellen, ob sich zwei Objekte berühren = collision detection
Daraus ergibt sich die allgemeine Skriptstruktur des MOUSE_UP-Eventhandlers:
function stopZiehen(e:MouseEvent):void {
e.target.stopDrag();
if (PRÜFEN, OB SICH GEZOGENES OBJEKT UND ZIELOBJEKT BERÜHREN) {
...
hier kommt der Code, der beschreibt was zu tun ist,
wenn sich die Objekte berühren.
Z.B. das Objekt "rastet" an einer bestimmten Stelle ein.
...
}
}
Es gibt nun drei einfache Möglichkeiten zu prüfen, ob sich zwei Objekte berühren bzw. ein Objekt vollständig innerhalb eines anderen liegt:
- Die DisplayObject-Methode hitTestObject
prüft, ob sich die Rechteckshüllen von zwei Anzeigeobjekten schneiden. - Die DisplayObject-Mehtode hitTestPoint
prüft, ob ein Punkt innerhalb der Objektkonturen bzw. der Rechteckshülle eines Anzeigeobjekts liegt. - Die DisplayObject-Methoden getRect bzw.getBounds in Verbindung mit der Rectangle-Methode containsRect.
ermittelt zuerst die Rechteckshüllen beider Objekte und prüft anschließend, ob ein Rechteck vollständig innerhalb des anderen liegt.
Das Video zeigt die unterschiedlichen Resultate der drei Möglichkeiten, die anschließend genau erklärt werden.
Der hellblaue Kreis als Zielobjekt ist eine Movieclipinstanz mit dem Namen ziel.
Wir gehen von folgendem Programmcode aus, den wir vom letzten Kapitel übernehmen und nur durch die markierte if-Anweisung erweitern.
// Stern durch Anklicken der Bühne erzeugen
this.stage.addEventListener(MouseEvent.MOUSE_UP,erzeugeStern);
function erzeugeStern(e:MouseEvent):void {
if (e.target == e.currentTarget) {
var stern:MovieClip = new GelberStern();
this.addChild(stern);
stern.x = e.stageX;
stern.y = e.stageY;
}
}
// Stern bei gedrückter Maustaste in den hellblauen Kreis ziehen
this.addEventListener(MouseEvent.MOUSE_DOWN, startZiehen);
function startZiehen(e:MouseEvent):void {
e.target.startDrag(false);
}
this.addEventListener(MouseEvent.MOUSE_UP, stopZiehen);
function stopZiehen(e:MouseEvent):void {
e.target.stopDrag();
if (PRÜFEN, OB SICH GEZOGENES OBJEKT UND ZIELOBJEKT BERÜHREN) {
e.target.x = ziel.x;
e.target.y = ziel.y;
}
}
Wenn sich das gezogene Objekt und das Zielobjekt berühren, wird der Ursprung des gezogenen Objekts auf den Ursprung des Zielobjekts ausgerichtet.
e.target.x = ziel.x;
e.target.y = ziel.y;
Es werden nun drei Möglchkeiten für collision detection gezeigt.
1. Möglichkeit mit hitTestObject
object1.hitTestObject(object2)
Ausgehend von einem Anzeigeobjekt object1 prüft die Methode hitTestObject, ob sich die kleinsten Rechteckshüllen von object1 und object2 überlappen.
Die Methode kann auch den Wert true liefern, wenn sich die eigentlichen Objektkonturen nicht schneiden.
In unserem Beispiel lautet daher die Abfrage in der if-Anweisung:
e.target.hitTestObject(ziel)
2. Möglichkeit mit hitTestPoint
object.hitTestPoint(x,y,true/false)
Ausgehend von einem Anzeigeobjekt object prüft die Methode hitTestPoint, ob der Punkt (x,y) innerhalb der Kontur bzw. der kleinsten Rechteckshülle des Anzeigeobjekts liegt.
Ist der dritte Parameter true gilt die tatsächliche Objektkontur als Bezug, sonst die kleinste Rechteckshülle.
Im obigen Fall liefert hitTestPoint bezogen auf den weißen Punkt den Wert true, wenn der dritte Parameter auf false gesetzt ist. Denn der weiße Punkt liegt nicht innerhalb der Objektkontur des Sterns, aber innerhalb der Rechteckshülle.
Wenn die tatsächliche Sternkontur als Bezug gelten soll, lautet daher in unserem Beispiel die Abfrage in der if-Anweisung:
e.target.hitTestPoint(ziel.x,ziel.y,true)
3. Möglichkeit mit getRect bzw. getBounds und containsRect
object1.getRect(object2)
object1.getBounds(object2)
Ausgehend von einem Anzeigeobjekt object1 liefert die Methode getRect (bzw. getBounds) eine Instanz der Klasse Rectangle, die das kleinste umhüllende Rechteck des Anzeigeobjekts beschreibt. Ein Objekt vom Typ Rectangle ist definiert durch die Koordinaten des linken oberen Eckpunkts und durch die Breite und Höhe des Rechtecks. Um die Koordinaten des linken oberen Eckpunkts angeben zu können, benötigt man ein Bezugssystem. Deshalb erhalten getRect und getBounds als Parameter ein Anzeigeobjekt object2, dessen Koordinatensystem das Bezugssystem für die Positionsangabe der Rechteckshülle von object1 ist.
Der Unterschied zwischen getRect und getBounds besteht darin, dass sich getRect auf die Konstruktionslinien des Objekts und getBounds auf die tatsächlichen Objektkonturen bezieht. Der Unterschied ist bei breiten Konturlinien am besten zu erkennen.
In unserem Beispiel ist das Bezugssystem die Bühne.
Die kleinsten umhüllenden Rechtecke vom hellblauen Kreis und vom Stern erhält man somit durch:
ziel.getRect(this.stage) // hellblauer Kreis
e.target.getRect(this.stage) // Stern
In der Klasse Rectangle gibt es eine Methode containsRect mit der man überprüfen kann, ob ein Rechteck rectangle2 vollständig in einem anderen Rechteck rectangle1 enthalten ist.
rectangle1.containsRect(rectangle2)
Wenn in unserem Beispiel der Stern vollständig in der Rechteckshülle des hellblauen Kreises liegen soll, lautet die Abfrage in der if-Anweisung:
ziel.getRect(this.stage).containsRect(e.target.getRect(this.stage))
Quellcode in der beigefügten zip-Datei:
dragdrop.fla
dragdrop1.fla
dragdrop2.fla
Drag and Drop - zurück zum Ausgangspunkt
Häufig sieht man folgende Variante von Drag and Drop:Wenn beim Loslassen der Maustaste das gezogene Objekt nicht über dem Ziel liegt, soll das Objekt wieder zum Ausgangspunkt zurückspringen. Oder umgekehrt formuliert: Beim Loslassen über einem "verbotenen" Bereich soll das Objekt wieder seine ursprüngliche Position einnehmen.
Zum Ausprobieren: Durch Klick auf die dunkelblaue Fläche einen Stern erzeugen. Wenn dieser nach dem Ziehen wieder über der dunkelblauen Fläche losgelassen wird, springt es zum Ausgangspunkt zurück.
Zu diesem Zweck muss man sich beim Anklicken des Objekts die momentane Position merken und beim Loslassen der Maustaste prüfen, ob das Objekt über dem Ziel liegt. Wenn das nicht der Fall ist, wird das Objekt auf die gespeicherte Ausgangsposition zurückgesetzt.
Wir definieren dazu zwei Variable startPosX und startPosY in denen die Ausgangsposition gespeichert wird:
var startPosX: Number;
var startPosY: Number;
Beim Anklicken des Objekts wird der Eventhandler startZiehen ausgeführt. Darin werden die x- und y-Koordinaten des angeklickten Objekts e.target in den beiden Variablen startPosX und startPosY gespeichert und damit für später gemerkt.
function startZiehen(e:MouseEvent):void {
e.target.startDrag(false);
startPosX = e.target.x;
startPosY = e.target.y;
}
Beim Loslassen der Maustaste wird der Eventhandler stopZiehen
ausgeführt. Darin wird nach einer der im letzten Kapitel vorgestellten
Methoden überprüft, ob das losgelassene Objekt über dem Ziel liegt.
Wenn das der Fall ist, wird das Objekt auf das Ziel ausgerichtet. Wenn
nicht, werden die x- und y-Koordinaten des gezogenen Objekts e.target auf die in startPosX und startPosY gespeicherten Ausgangswerte zurückgesetzt.
function stopZiehen(e:MouseEvent):void {
e.target.stopDrag();
if (e.target.hitTestObject(ziel)) {
e.target.x = ziel.x;
e.target.y = ziel.y;
} else {
e.target.x = startPosX;
e.target.y = startPosY;
}
}
Zusammengefasst ergibt sich folgendes Skript im ersten Frame der Maintimeline:
// Stern durch Anklicken der Bühne erzeugen
this.stage.addEventListener(MouseEvent.MOUSE_UP,erzeugeStern);
function erzeugeStern(e:MouseEvent):void {
if (e.target == e.currentTarget) {
var stern:MovieClip = new GelberStern();
this.addChild(stern);
stern.x = e.stageX;
stern.y = e.stageY;
}
}
// Stern bei gedrückter Maustaste ziehen
var startPosX: Number;
var startPosY: Number;
this.addEventListener(MouseEvent.MOUSE_DOWN, startZiehen);
function startZiehen(e:MouseEvent):void {
e.target.startDrag(false);
startPosX = e.target.x;
startPosY = e.target.y;
}
this.addEventListener(MouseEvent.MOUSE_UP, stopZiehen);
function stopZiehen(e:MouseEvent):void {
e.target.stopDrag();
if (e.target.hitTestObject(ziel)) {
e.target.x = ziel.x;
e.target.y = ziel.y;
} else {
e.target.x = startPosX;
e.target.y = startPosY;
}
}
Wo müssen die Variblen startPosX und startPosY deklariert werden?
Da die Variablen startPosX und startPosY in den beiden Funktionen stopZiehen und startZiehen verwendet werden, muss die var-Deklaration außerhalb der Funktionen erfolgen.
Wir können daher, wie im obigen Beispiel den Deklarationsblock
var startPosX: Number;
var startPosY: Number;
- im Skript der Maintimeline außerhalb der Funktionsdefinitionen platzieren oder
- im ersten Frame des Movieclips GelberStern. In diesem Fall sind die Variablen Eigenschaften des Movieclips.
Um die beiden Variablen in den Funktionsdefinitionen von startZiehen und stopZiehen richtig anzusprechen muss mane.target.startPosX bzw. e.target.startPosY
schreiben, weil sie Eigenschaften des angeklickten Objekts sind.
Verfeinerung des Skripts:
Mit
dem obigen Skript kann man einen Stern, der einmal in den hellblauen
Kreis gezogen wurde, nicht mehr aus diesem herausziehen.
Wenn man das ermöglichen möchte, muss man eine weitere boolsche Variable hitTest einführen, in der gespeichert wird, ob die Ausgangsposition des Sterns über dem hellblauen Kreis war oder nicht.
Beim Loslassen der Maustaste über der dunkelblauen Fläche (d.h. außerhalb des Ziels) wird dann die Variable hitTest abgefragt. Nur wenn die Ausgangsposition nicht über dem hellblauen Kreis war (hitTest hat den Wert false) erfolgt das Zurückspringen in die Ausgangsposition.
var startPosX: Number;
var startPosY: Number;
var hitTest:Boolean;
this.addEventListener(MouseEvent.MOUSE_DOWN, startZiehen);
function startZiehen(e:MouseEvent):void {
e.target.startDrag(false);
startPosX = e.target.x;
startPosY = e.target.y;
if (e.target.hitTestObject(ziel)) {
hitTest = true;
} else {
hitTest = false;
}
}
this.addEventListener(MouseEvent.MOUSE_UP, stopZiehen);
function stopZiehen(e:MouseEvent):void {
e.target.stopDrag();
if (e.target.hitTestObject(ziel)) {
e.target.x = ziel.x;
e.target.y = ziel.y;
} else {
if (hitTest == false) {
e.target.x = startPosX;
e.target.y = startPosY;
}
}
}
Quellcode in der beigefügten zip-Datei:
dragDrop_back.fla
dragDrop_back1.fla
Erzeugte Objekte durch Klick mit gedrückter Strg-Taste oder durch Doppelklick löschen
Für das Löschen von auf der Bühnen liegenden Sprite- oder Movieclipinstanzen gibt es wieder wie im letzten Kapitel zwei Möglichkeiten: Entweder man platziert das Skript in der Timeline des Movieclips (für Sprites in der Klassendefinition) oder in der Maintimeline.
Grundsätzlich wird eine Movieclipinstanz gelöscht, wenn diese aus der Displayliste entfernt wird und keine weiteren Verweise auf die Instanz existieren. Erst wenn die Instanz nicht mehr z.B. über eine Variable erreichbar ist, eliminiert die Garbagecollection des Flash-Player die Instanz automatisch aus dem Speicher.
Wichtig:
Das Entfernen aus der Displayliste bedeutet noch nicht zwingend, dass die Instanz entgültig gelöscht ist. Sie ist nur nicht mehr sichtbar. Erst wenn sie nicht mehr erreichbar ist, wird sie gelöscht.
In unserem Beispiel werden die Sterne durch das Entfernen aus der Displayliste auch gelöscht, da keine weiteren Verweise existieren.
Durch die Methoden removeChild und removeChildAt können Objekte aus der Displayliste entfernt werden (siehe auch Displayliste).
Wenn man nun ein Objekt anklickt, so ist dieses Objekt das Zielobjekt (target) des Ereignisses. Mit nachfolgenden Schritten wird das Zielobjekt aus der Displayliste entfernt. Dabei ist e das Ereignisobjekt, das an den Eventlistener übergeben wird und e.target das angeklickte Zielobjekt.
1. Elternobjekt des Zielobjekts:
2. Vom Zielobjekt wird sein Index in der Displayliste des Elternobjekts ermittelt:e.target.parent
3. Das Elternobjekt löscht das Zielobjekt (= Kind) an der Stelle des ermittelten Index. Das Kind (Zielobjekt) gibt quasi seinen Eltern den Auftrag, es aus der Displayliste zu entfernen.e.target.parent.getChildIndex(e.target)
e.target.parent.removeChildAt(e.target.parent.getChildIndex(e.target))
Löschen durch Anklicken bei gedrückter Strg-Taste:
Das ergibt folgendes Skript für das Löschen eines Objekts aus der Displayliste durch Anlicken bei gedrückter Strg-Taste.
Das Skript kann im ersten Frame der Maintimeline oder der Movieclip-Timeline platziert werden. Im ersten Fall gilt das Skript für alle möglichen interaktiven Objekte auf der Bühne, im zweiten Fall nur für die Sterne.
this.addEventListener(MouseEvent.MOUSE_UP, loeschen);
function loeschen(e:MouseEvent):void {
if (e.ctrlKey == true) {
e.target.parent.removeChildAt(e.target.parent.getChildIndex(e.target));
}
}
Der Ausdruck e.ctrlKey liefert den Wert true, wenn zum Zeitpunkt des Mausereignisses die Strg-Taste gedrückt wurde. Nur unter dieser Bedingung wird das Objekt aus der Dispalyliste entfernt.
Zum Ausprobieren: Erst Stern erzeugen, dann mit gedrückter Strg-Taste auf den Stern klicken.
Löschen durch Doppelklick:
Damit eine InteractiveObject-Instanz auf einen Doppelklick reagieren kann, muss die Eigenschaft doubleClickEnabled auf true gesetzt werden. Standardmäßig ist der Wert false.
D.h. wir können entweder beim Erzeugen eines neuen Sterns die Eigenschaft setzen ...
this.stage.addEventListener(MouseEvent.MOUSE_DOWN,erzeugeStern);
function erzeugeStern(e:MouseEvent):void {
if (e.target == e.currentTarget) {
var stern:MovieClip = new GelberStern();
stern.doubleClickEnabled = true;
this.addChild(stern);
stern.x = e.stageX;
stern.y = e.stageY;
}
}
... oder gleich im ersten Frame des Movieclip-Skripts GelberStern
this.doubleClickEnabled = true;
....
Anschließend registriert sich das Mainmovie oder der Movieclip mit dem Eventlistener loeschen beim Mausereignis DOUBLE_CLICK.
D.h. das Skript kann wieder im ersten Frame der Maintimeline oder der Movieclip-Timeline platziert werden.
this.addEventListener(MouseEvent.DOUBLE_CLICK, loeschen);
function loeschen(e:MouseEvent):void {
e.target.parent.removeChildAt(e.target.parent.getChildIndex(e.target));
}
Der Eventlistener enthält wieder die removeChildAt-Anweisung, die oben erklärt wurde.
Zum Ausprobieren: Erst Stern erzeugen, dann auf den Stern doppelklicken.
Quellcode in der beigefügten zip-Datei:
createObjectsClickDragDelete.fla
createObjectsClickDragDelete1.fla
createObjectsClickDragDeleteDoubleClick.fla
Objekte erzeugen, während die Maus bewegt wird
MOUSE_MOVE ist ein wesentliches Mausereignis, das permanent auftritt, solange der Mauszeiger bewegt wird.
MOUSE_MOVE-Ereignisse können viel öfter als ENTER_FRAME-Ereignisse auftreten und sind von diesen unabhängig.
Wenn man daher in Abhängigkeit von der Mausbewegung ein Programm steuern möchte, dann ist die Verwendung von Eventhandlern für MOUSE_MOVE-Ereignisse besser geeignet als für ENTER_FRAME-Ereignisse. Siehe auch Cursor-Modul.
Im nachfolgenden Beispiel werden permanent beim Bewegen des Mauszeigers über die Bühne kleine Kreise an der momentanen Mausposition erzeugt. Dieses Beispiel veranschaulicht auf niedrigem Niveau das Grundprinzip des Linienzeichnens in Grafikprogrammen. Der Kreis wäre eine Werkzeugspitze mit bestimmter Größe, Form, Farbe und Deckkraft.
Zum Ausprobieren: Bewegen Sie den Mauszeiger über die Bühne.
Dazu ist in der Bibliothek ein MovieClip Kreis abgelegt, beim die Eigenschaft Export für ActionScript aktiviert ist. Der Klassenname ist ebenfalls Kreis.
Im ersten Frame der Maintimeline wird nachstehendes Skript geschrieben:
var kreis:MovieClip;
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
function drawCircle(e:MouseEvent):void {
kreis = new Kreis();
this.addChild(kreis);
kreis.x = e.stageX;
kreis.y = e.stageY;
}
Erklärungen zum Skript:
Zuerst wird eine Variable kreis von Typ MovieClip definiert. Sie könnte in diesem Fall auch z.B. vom Typ DisplayObject oder Sprite sein.
var kreis:MovieClip;
Anschließend abonniert die Bühne das Ereignis MOUSE_MOVE mit dem Eventandler drawCircle.
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
In der Eventhandlerfunktion drawCircle, die immer ausgeführt wird, wenn die Maus bewegt und das Ereignis MOUSE_MOVE vom Flash-Player generiert wird, wird eine neue Instanz des Movieclips Kreis erzeugt, ...
kreis = new Kreis();
... der Displayliste des Mainmovies hinzugefügt ...
this.addChild(kreis);
... und auf die Position des Mauszeigers platziert.
kreis.x = e.stageX;
kreis.y = e.stageY;
Der Eingabeparameter e ist vom Typ MouseEvent. Über die MouseEvent-Eigenschaften stageX und stageY kann immer die Mausposition zum Zeitpunkt des Ereignisses relativ zur Bühne abgefragt werden. Siehe auch Kapitel 1 und 2 in diesem Modul.
Im nächsten Kapitel wird das Beispiel erweitert, indem man nur bei gedrückter Maustaste beim Bewegen der Maus die Kreise zeichnen kann.
Quellcode in der beigefügten zip-Datei:
MouseEvent_Kreise_zeichnen.fla
Objekte erzeugen, nur wenn die Maus bei gedrückter linker Maustaste bewegt wird
Im diesem Kapitel wird das Beispiel aus dem Vorkapitel erweitert, indem man nur bei gedrückter Maustaste beim Bewegen der Maus die Kreise zeichnen kann.
Dieses Beispiel ist prototypisch für viele Skripts, bei denen durch die Ausführung eines Eventhandlers ein anderer Eventhandler aktiviert bzw. deaktiviert wird.
Zum Ausprobieren: Nur wenn Sie bei gedrückter Maustaste die Maus bewegen, werden Kreise gezeichnet. Es werden beim Bewegen der Maus keine Kreise generiert, wenn Sie die Maustaste nicht gedrückt halten.
Im Vorkapitel registriert sich die Bühne durch
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
beim Ereignis MOUSE_MOVE. Diese Registrierung wird nicht mehr durch removeEventListener aufgehoben und daher werden permanent beim Bewegen der Maus durch den Eventhandler drawCircle Kreise gezeichnet.
In diesem Beispiel soll aber die Registrierung beim Ereignis MOUSE_MOVE erst dann erfolgen, wenn die Maustaste niedergedrückt wird.
D.h. die Bühne registriert sich zuerst beim Ereignis MOUSE_DOWN mit einem Eventhandler startDrawing. Erst beim Ausführen dieses Eventhandlers abonniert die Bühne das MOUSE_MOVE-Ereignis. Dadurch wird erst beim Drücken der Maus der Eventhandler für MOUSE_MOVE aktiviert.
this.stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing );
function startDrawing(e:MouseEvent):void {
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
}
Die Registrierung beim MOUSE_MOVE-Ereignis muss wieder aufgehoben werden, wenn die Maustaste losgelassen wird.
D.h. die Bühne muss sich auch beim Ereignis MOUSE_UP mit einem Eventhandler stopDrawing registrieren. Bei der Ausführung dieses Eventhandlers wird die Registrierung beim MOUSE_MOVE-Ereignis mit dem Eventhandler drawCircle durch removeEventListener wieder deaktiviert. Daher werden nach dem Loslassen der Maustaste beim Bewegen der Maus keine Kreise mehr gezeichnet.
this.stage.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
function stopDrawing(e:MouseEvent):void {
this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
}
Nachfolgend das vollständige Skript im ersten Frame der Maintimeline:
var kreis:MovieClip;
this.stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing );
function startDrawing(e:MouseEvent):void {
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
}
function drawCircle(e:MouseEvent):void {
kreis = new Kreis();
this.addChild(kreis);
kreis.x = e.stageX;
kreis.y = e.stageY;
}
this.stage.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
function stopDrawing(e:MouseEvent):void {
this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawCircle);
}
Quellcode in der beigefügten zip-Datei:
MouseEvent_Kreise_zeichnen1.fla