Endloses Scrollen von 360°-Panoramen

Oft steht man vor der Aufgabe, ein 360°-Panoramabild in eine swf-Datei einzubinden, in dem man sich in beide Richtungen endlos im Kreis drehen kann.
Wie man professionell Panoramabilder aufnimmt, zeigt folgendes Video aus www.foto-podcast.de

In der nachstehenden swf-Datei kann man durch Rollover über die Dreiecke an den seitlichen Rändern das Panorama endlos nach links oder rechts verschieben.
 

 

Das Panoramabild (hier der Hauptplatz von Linz im Winter) wird in einem Bildbearbeitungsprogramm so vorbereitet, dass die linke und rechte Bildkante identisch sind.

Abschließend wird in der Größe der Bühne das linke Ende des Panoramas noch einmal an die rechte Panoramakante angehängt.
Das ist notwendig, um das endlose Rotieren zu ermöglichen.
Im nachstehenden Bild sind die beiden blau umrandeten Rechtecke identisch und haben die Größe der Bühne.
Dieses Bild wird der Inhalt des zu rotierenden Containers.

Die beiden Scrollbuttons liegen in einer eigenen Ebene und sind auf die seitlichen Ränder ausgerichtet.
Bei Rollover wird nun die Movieclipinstanz analog zu Kapitel 2: Scrollen eines Containers nach links bzw. rechts bewegt.

Skript (panorama360_scroll.fla):

Wir übernehmen dafür aus dem zweiten Kapitel Scrollen eines Containers das Skript aus dem 1. Schritt Scrollen des Containers OHNE Behandlung des Bildrandproblems. Die Ergänzungen für das endlose Rotieren sind hervorgehoben und werden anschließend erklärt.
 

var schrittweite:int=15;
links_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
rechts_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
function startScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
panorama_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
panorama_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
break;
}
}
links_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
rechts_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
function stopScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
panorama_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
panorama_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
break;
}
}
function nachLinks(e:Event) {
e.target.x -= schrittweite;
if (e.target.x + e.target.width < stage.stageWidth) {
e.target.x += e.target.width - stage.stageWidth;
}

}
function nachRechts(e:Event) {
e.target.x += schrittweite;
if (e.target.x > 0) {
e.target.x -= e.target.width - stage.stageWidth;
}
}

In der if-Anweisung der Funktionen nachLinks wird geprüft, ob nach Abzug der Schrittweite die rechte Containerkante bereits die rechte Bühnenkante erreicht hat. Wenn das der Fall ist, wird der ganze Container um (Containerbreite - Bühnebreite) nach rechts versetzt. Da die beiden Enden des Containers identisch sind, ändert sich das gezeigte Bild nicht, aber der Container kann jetzt weiterhin nach links verschoben werden.

In der if-Anweisung der Funktionen nachRechts wird geprüft, ob nach Hinzufügen der Schrittweite die linke Containerkante bereits die linke Bühnenkante erreicht hat. Wenn das der Fall ist, wird der ganze Container um (Containerbreite - Bühnebreite) nach links versetzt. Da die beiden Enden des Containers identisch sind, ändert sich das gezeigte Bild nicht, aber der Container kann jetzt weiterhin nach rechts verschoben werden.


Wichtige Anmerkung:

Bei dieser Methode wird die exakte Bühnengröße schon im Voraus in das Panoramabild eingearbeitet. Daher sollte man verhindern, dass die BenutzerInnen das Player-Fenster skalieren können ohne dass der Inhalt angepasst wird. 

Man kann das verhindern, wenn man den ScaleMode der Bühne auf

stage.scaleMode = StageScaleMode.EXACT_FIT; (Proportionen bleiben nicht erhalten)

oder

stage.scaleMode = StageScaleMode.NO_BORDER; (Proportionen bleiben erhalten)

setzt.

 

2. Möglichkeit: Zwei Container verwenden (panorama360_scroll_2Teile.fla)

Wenn man im Panoramabild nicht das linke Ende noch einmal am rechten Ende wiederholen möchte, gibt es die Möglichkeit, das Bild exakt in der Hälfte zu teilen und jede Hälfte in einen eigenen Container zu legen.
Dabei wird ein Container, sobald er in Scrollrichtung aus der Bühne hinaus bewegt wurde, hinter dem anderen Container positioniert.

Das Skript zum Selbststudium ohne weitere Erklärung

var schrittweite:int=15;
 
links_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
rechts_btn.addEventListener(MouseEvent.ROLL_OVER, startScrollen);
 
function startScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
panorama1_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
panorama2_mc.addEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
panorama1_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
panorama2_mc.addEventListener(Event.ENTER_FRAME, nachLinks);
break;
}
}
 
links_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
rechts_btn.addEventListener(MouseEvent.ROLL_OUT, stopScrollen);
function stopScrollen(e:MouseEvent):void {
switch (e.target) {
case links_btn :
panorama1_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
panorama2_mc.removeEventListener(Event.ENTER_FRAME, nachRechts);
break;
case rechts_btn :
panorama1_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
panorama2_mc.removeEventListener(Event.ENTER_FRAME, nachLinks);
break;
}
}
 
function nachLinks(e:Event) {
e.target.x-=schrittweite;
// Neupositionierung: Der Container wird um seine doppelte Länge nach rechts verschoben.
if (e.target.x+e.target.width < 0) {
e.target.x = e.target.x + 2 * e.target.width;
}

}
function nachRechts(e:Event) {
e.target.x+=schrittweite;
// Neupositionierung: Der Container wird um seine doppelte Länge nach links verschoben.
if (e.target.x > stage.stageWidth) {
e.target.x = e.target.x - 2 * e.target.width;
}
}