Scrollen eines Containers

In dem nachfolgenden swf-Beispiel kann das Luftbild mittels der vier Buttons an den Bühnenrändern nach links, rechts, oben und unten gescrollt werden. Beim Erreichen eines Bildrandes wird der Scrollvorgang beendet und der entsprechende Button wird ausgeblendet, da das Bild nicht mehr weitergescrollt werden kann. Betätigt man den gegenüberliegenden Button wird der ausgeblendete Button wieder sichtbar.
Es wurden dabei zwei Varianten realisert:

Bei dem linken und rechten Button wird der Scrollvorgang durch Anklicken der Buttons gestartet und durch Loslassen der Maustaste über den Buttons wieder gestoppt.
Bei dem oberen und unteren Button wird der Scrollvorgang durch Rollover gestartet und durch Rollout wieder gestoppt. Das ist für mich die elegantere Lösung.

Anmerkung: Bei der Gestaltung der Buttons ist man natürlich völlig frei. Es könnte z.B. auch entlang  jeder Bühnenseite ein schmales, unsichtbares Rechteck als Button platziert werden. Wenn man sich mit dem Mauszeiger einem Rand nähert, wird durch Rollover der Scrollvorgang gestartet und bei Rollout wieder gestoppt.
 

 

In der Bibliothek liegen ein Movieclip, der als einziges Element das Luftbild der Altstadt von Linz enthält und eine dreieckige Schaltfläche.
Eine Instanz des Movieclipcontainers liegt im ersten Frame des Mainmovies und hat den Instanznamen container_mc.
Vier Instanzen der Schaltfläche werden an den Rändern positioniert, entsprechend gedreht und erhalten die Instanznamen links_btn, rechts_btn, oben_btn und unten_btn.
Anmerkung: Nur für die Abbildung wurde die Deckkraft des Containers reduziert, um auch die Bühne zu zeigen.


 

1. Schritt: Scrollen des Containers OHNE Behandlung des Bildrandproblems

Das nachfolgende Skript wird im ersten Frame der Timeline des Mainmovies platziert (scroll_movieclip.fla):
 

var schrittweite:int=5;
 
links_btn.addEventListener(MouseEvent.MOUSE_DOWN, startScrollen);
rechts_btn.addEventListener(MouseEvent.MOUSE_DOWN, startScrollen);
oben_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
unten_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
 
function startScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}
 
links_btn.addEventListener(MouseEvent.MOUSE_UP, stopScrollen);
rechts_btn.addEventListener(MouseEvent.MOUSE_UP, stopScrollen);
oben_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
unten_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
 
function stopScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}
 
function nachLinks(e:Event) {
e.target.x-=schrittweite;
}
function nachRechts(e:Event) {
e.target.x+=schrittweite;
}
function nachOben(e:Event) {
e.target.y-=schrittweite;
}
function nachUnten(e:Event) {
e.target.y+=schrittweite;
}


Schrittweise Erklärung des Skripts:

Grundidee: Die vier Scrollbuttons abonnieren das Ereignis MOUSE_DOWN bzw. ROLL_OVER mit dem Eventhandler startScrollen.
In Abhängigkeit davon, welcher Button aktiviert wurde, wird dem Container ein ENTER_FRAME-Eventhandler zugeordnet, der bei jedem ENTER_FRAME-Ereignis den Container um die vordefinierte Schrittweite weiterschiebt.
Beim Loslassen der Maustaste bzw. bei Rollout wird der ENTER_FRAME-Eventhandler wieder vom Container entfernt.

 

var schrittweite:int=5;

In der ganzzahligen Variablen schrittweite wird festgelegt, um wieviele Pixel der Container bei jedem ENTER_FRAME-Ereignis weitergeschoben wird.

 

links_btn.addEventListener(MouseEvent.MOUSE_DOWN, startScrollen);
rechts_btn.addEventListener(MouseEvent.MOUSE_DOWN, startScrollen);
oben_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
unten_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);

Die vier Buttoninstanzen abonnieren das Ereignis MOUSE_DOWN bzw. ROLL_OVER mit dem Eventhandler startScrollen.

 

function startScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
container_mc.addEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}

e.target liefert die Buttoninstanz, die aktiviert wurde. Im switch-Statement wird jede einzelne Buttoninstanz abgefragt und in Abhängigkeit davon abonniert mit addEventListener der Container für das ENTER_FRAME-Ereignis einen anderen Eventhandler.
Wenn der linke Button aktiviert wurde, wird der Container nach rechts geschoben, beim rechten Button nach links, beim oberen Button nach unten und beim unteren Button nach oben.

 

function nachLinks(e:Event) {
e.target.x-=schrittweite;
}
function nachRechts(e:Event) {
e.target.x+=schrittweite;
}
function nachOben(e:Event) {
e.target.y-=schrittweite;
}
function nachUnten(e:Event) {
e.target.y+=schrittweite;
}

e.target liefert den Container. Die vier ENTER_FRAME-Eventhandler (für jeden Button einen) erhöhen bzw. reduzieren je nach Richtung den x- bzw. y-Wert des Containers.
Z.B. wenn der Container nach oben bewegt wird, wird die Schrittweite vom y-Wert abgezogen.

 

links_btn.addEventListener(MouseEvent.MOUSE_UP, stopScrollen);
rechts_btn.addEventListener(MouseEvent.MOUSE_UP, stopScrollen);
oben_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
unten_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);

Die vier Buttoninstanzen abonnieren auch das Ereignis MOUSE_UP bzw. ROLL_OUT mit dem Eventhandler stopScrollen.

 

function stopScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}

e.target liefert wieder die entsprechende Buttoninstanz. Im switch-Statement wird jede einzelne Buttoninstanz abgefragt und in Abhängigkeit davon wird der dazugehörige ENTER_FRAME-Eventhandler mit removeEventListener vom Container entfernt.

 

2. Schritt: Scrollen des Containers MIT Behandlung des Bildrandproblems

Das nachfolgende Skript wird im ersten Frame der Timeline des Mainmovies platziert (scroll_movieclip_limits.fla):

Die Ergänzungen sind hervorgehoben.

var schrittweite:int=5;
 
links_btn.addEventListener(MouseEvent.MOUSE_DOWN, startScrollen);
rechts_btn.addEventListener(MouseEvent.MOUSE_DOWN, startScrollen);
oben_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
unten_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
 
function startScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
rechts_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
links_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
unten_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
oben_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}
 
links_btn.addEventListener(MouseEvent.MOUSE_UP, stopScrollen);
rechts_btn.addEventListener(MouseEvent.MOUSE_UP, stopScrollen);
oben_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
unten_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
 
function stopScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
container_mc.removeEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}
 
function nachLinks(e:Event) {
container_mc.x-=schrittweite;
if (container_mc.x < stage.stageWidth-container_mc.width) {
container_mc.x=stage.stageWidth-container_mc.width;
rechts_btn.visible=false;
container_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
}
}
function nachRechts(e:Event) {
container_mc.x+=schrittweite;
if (container_mc.x > 0) {
container_mc.x=0;
links_btn.visible=false;
container_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
}
}
function nachOben(e:Event) {
container_mc.y-=schrittweite;
if (container_mc.y < stage.stageHeight-container_mc.height) {
container_mc.y=stage.stageHeight-container_mc.height;
unten_btn.visible=false;
container_mc.removeEventListener(Event.ENTER_FRAME, nachOben);
}
}
function nachUnten(e:Event) {
container_mc.y+=schrittweite;
if (container_mc.y > 0) {
container_mc.y=0;
oben_btn.visible=false;
container_mc.removeEventListener(Event.ENTER_FRAME, nachUnten);
}
}


Schrittweise Erklärung der Erweiterungen:

Es werden hier nur mehr die Abschnitte besprochen, die sich gegenüber dem ersten Schritt geändert haben.

function startScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
rechts_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
links_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
break;
case oben_btn :
unten_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachUnten);
break;
case unten_btn :
oben_btn.visible=true;
container_mc.addEventListener(Event.ENTER_FRAME, nachOben);
break;
}
}

Bei Aktivierung eines Buttons wird auf jeden Fall der gegenüberliegende Button sichtbar gemacht.
Denn es kann der Fall eintreten, dass ein Button unsichtbar ist, weil der Rand erreicht wurde. Wenn nun der gegenüberliegende Button aktiviert wird und sich der Container in Gegenrichtung vom Rand weg bewegt, muss der unsichtbare Button wieder sichtbar gemacht werden.
Falls der Container keine Randlage einnimmt, ist der Button ohnehin sichtbar und die Anweisung xxx_btn.visible = true verändert nichts.

 

function nachRechts(e:Event) {
container_mc.x+=schrittweite;
if (container_mc.x > 0) {
container_mc.x=0;
links_btn.visible=false;
container_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
}
}
function nachLinks(e:Event) {
container_mc.x-=schrittweite;
if (container_mc.x < stage.stageWidth-container_mc.width) {
container_mc.x=stage.stageWidth-container_mc.width;
rechts_btn.visible=false;
container_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
}
}

Stellvertretend werden die Eventhandler nachRechts und nachLinks besprochen:
Zuerst wird der Container um die Schrittweite bewegt. Dabei kann es passieren, dass der Bildrand bereits innerhalb der Bühne liegt.
Daher wird in der darauf folgenden if-Anweisung geprüft, ob das der Fall ist:
In der Funktion nachRechts ist der linke Bildrand innerhalb der Bühne, wenn container_mc.x>0 gilt. Wenn das der Fall ist, wird der x-Wert des Containers auf 0 gesetzt (d.h. der linke Bildrand ist gleich dem linken Bühnenrand), der linke Button wird unsichtbar gesetzt und der ENTER_FRAME-Eventhandler nachtRechts wird vom Container entfernt, da keine Rechtbewegung mehr gemacht werden darf.
In der Funktion nachLinks ist der rechte Bildrand innerhalb der Bühne, wenn container_mc.x gilt. Wenn das der Fall ist, wird der x-Wert des Containers auf stage.stageWidth-container_mc.width gesetzt (d.h. der rechte Bildrand ist gleich dem rechten Bühnenrand), der rechte Button wird unsichtbar gesetzt und der ENTER_FRAME-Eventhandler nachtLinks wird vom Container entfernt, da keine Linksbewegung mehr gemacht werden darf.

Analoge Überlegungen gelten für die Eventhandler nachUnten und nachOben.