Drag and Drop mit Javascript
Online-Puzzle

DeveloperIT-ProjekteSoftware

Drang-and-Drop gibt es auf Websites nicht erst seit Web 2.0 und Ajax. Mit ein wenig Javascript und Layern geht es auch. Wie, das zeigt dieser Workshop am Beispiel eines Puzzles.

Darum geht’s

Drag and Drop mit Javascript

Alles schwärmt von Ajax und den neuen Möglichkeiten, die die Technik mit sich bringt. Manche Funktionen lassen sich jedoch bereits mit ein wenig Javascript und Layern nachbilden und erfordern nicht so viele Programmierkenntnisse.

In einem ersten Beispiel zeigt der Artikel Ihnen die Grundlagen, die Sie benötigen, um Objekte frei über den Bildschirm zu bewegen. Darauf aufbauend erfahren Sie, wie Sie Ihren Besuchern Puzzles anbieten, damit sie länger auf Ihrer Website verweilen. Zum Schluss bauen Sie einen einfachen Warenkorb auf. Das erste Listing dient zum Veranschaulichen des Sachverhalts. Deswegen ist es auch recht einfach gehalten.


Die Grundlagen

Drag and Drop mit Javascript

Als Basis benötigen Sie Objekte, die Sie auf dem Bildschirm hin und her bewegen können. Damit dies gelingt, müssen diese Layer-basiert sein. Im Beispiel wird auf die Integration von Bildern verzichtet. Sie beschränken sich auf vier bunte Blöcke, die Sie am linken Rand der Seite platzieren. Allen Quadraten ist Programmcode für das Ereignis onmousedown hinterlegt, das beim Anklicken mit der linken Maustaste aktiv wird.

Beim Zugriff auf das jeweilige Quadrat wird die Funktion prepare_move() mit einem Zeiger auf den angeklickten Layer übergeben.

Bevor es jedoch losgeht, wird die aktuelle Position des Mauszeigers über die Funktion get_ready() ermittelt. Diese wird initial beim Aufruf der Seite über das Ereignis onload des Body-Bereichs aufgerufen.

Die Funktion get_ready() arbeitet zwei Ereignisse ab: das Bewegen der Maus und das Loslassen der linken Maustaste.


function get_ready() {
document.onmousemove = start_moving;
document.onmouseup = stop_moving;
}

Hinter der ersten Funktion start_moving() steckt der wichtigste Teil des kompletten Skripts. Als Erstes stellen Sie hier, abhängig vom Browser, die x- und y-Koordinate des Mauszeigers fest.

Ist bereits eines der Quadrate in der Bewegung, kommt auch der zweite Teil von start_moving() zum Tragen. Er dient zum Positionieren des Quadrats und ermittelt aus den Koordinaten von Maus und der Startposition des Objekts die neue Position.


function start_moving(event) {
mouse_x = document.all ? window.event.clientX : event.pageX;
mouse_y = document.all ? window.event.clientY : event.pageY;
if(active_object != null) {
active_object.style.left = (mouse_x - start_x) + "px";
active_object.style.top = (mouse_y - start_y) + "px";
}
}

Wird eines der Objekte angeklickt und bewegt, so startet dies wie beschrieben das Ereignis prepare_move() und übergibt einen Zeiger auf das Quadrat.

Den Zeiger weisen Sie als Erstes der globalen Variablen active_obj zu. Danach bereiten Sie die Bewegung des Quadrats vor und ermitteln dafür die x- und y-Koordinaten. Dazu ziehen Sie die aktuelle Mausposition und die linke obere Ecke des Quadrats als Orientierungspunkte heran.


function prepare_move(obj) {
active_object = obj;
start_x = mouse_x - active_object.offsetLeft;
start_y = mouse_y - active_object.offsetTop;
}

Das Ereignis onmouseup beendet das Verschieben des Objekts. Die Verknüpfung mit der Funktion Stop_moving() bewirkt, dass die Variable active_obj wieder initialisiert wird und bereit ist, das nächste bewegte Objekt aufzunehmen.


function stop_moving() {
active_object=null;
}


Das Puzzle

Drag and Drop mit Javascript

Damit haben Sie nun das Handwerkszeug für das zweite Beispiel, ein Puzzle. Dazu nutzen Sie an Stelle der bunten Blöcke Bilder. Dies ist recht
einfach möglich, indem Sie innerhalb der div-Klammern der Style-Eigenschaft noch die Variable background-image mit dem Link für das Puzzle-Teil notieren. Damit sieht die neue div-Zeile dann folgendermaßen aus:

Als Bild haben die Autoren im Beispiel das Titelbild der Juli-Ausgabe der Internet Professionell benutzt, es in sechs gleich große Teile zerschnitten und im GIF-Format abgespeichert.

Die Grafiken sind wieder am linken Rand der Seite angeordnet. Neu ist auch der Parameter z-index für die Layer mit den Bildelementen. Als Hilfe zur Platzierung der Elemente gibt es noch ein Raster, auf dem Ihre Besucher die einzelnen Bilder ablegen können. Aufgebaut wird dieses durch eine einzelne Grafik, die insgesamt sechs Mal auf dem Bildschirm angeordnet ist. Damit die Titelseite nicht hinter dem Platzierungsraster verschwindet, wird der z-Index benötigt. Dieser legt fest, in welcher Ebene das Bild abgelegt wird. Für das Beispiel sind nur zwei Ebenen notwendig. Dem Raster weisen Sie den z-Index -1 zu, den Bildern einen beliebigen Wert, der größer ist – hier 40. Damit erscheint bei Bewegung das Bild vor dem Raster.


Magnetisches Raster

Drag and Drop mit Javascript

Beim Testen haben Sie sicherlich auch festgestellt, dass das Platzieren auf dem Raster möglich, aber nicht einfach ist. Deswegen integrieren Sie im nächsten Schritt noch eine weitere Funktion, die das Raster mit einer Art Magnet versieht. Sobald Sie ein Bild auf dem Grid abgelegt haben, wird es automatisch dem Ausschnitt zugewiesen, der vom Bild am meisten überlappt wird. Dies ist über die Funktion glue_ruler() realisiert.

Die Funktion berechnet die Differenz zwischen der linken oberen Ecke des Titelbilds und den Koordinaten des vorgegebenen Rasters. Wird das Bild aufs Raster platziert, ändert die Funktion die Koordinaten auf den genauen Wert und passt das Bild ein. Ist nicht ganz klar, ob das Bild nach links oder rechts soll, wird anhand der Überlappung das nächstgelegene Quadrat des Rasters ausgesucht. Für die Analyse greifen Sie auf zwei Hilfsvariablen zurück. Mit diffx findet eine Berechnung des finalen x-Werts statt, mit diffy die der y-Koordinate.


diffx = active_object.offsetLeft-125;

if(diffx>125)
active_object.style.left = '330px';
else
active_object.style.left = '200px';

diffy = active_object.offsetTop-117;

Da Sie ein 2×3-Raster haben, sind für die x-Koordinate nur zwei Durchgänge notwendig, während die y-Koordinate bis zu drei Anläufe benötigt.


if (diffy<0)
active_object.style.top='100px';

if (diffy>0 && diffy<120)
active_object.style.top='222px';

if (diffy>120)
active_object.style.top='345px';

Der Aufruf der Funktion glue_ruler() findet zum Abschluss der Bewegung statt, also als erster Aufruf innerhalb der Funktion stop_moving(), bevor der Zeiger auf das aktive Objekt wieder gelöscht wird.


Puzzleteile mischen

Drag and Drop mit Javascript

Nach dieser Erweiterung haben Sie nun also ein Puzzle, bei dem die einzelnen Teile zu Beginn noch recht geordnet auf der linken Seite des Fensters stehen. Das Hauptbild wird beim Zerschneiden meist der Reihe nach nummeriert, so dass bei einer sequenziellen Anordnung der Teilbilder sich das Zusammensetzen recht einfach gestaltet.

Damit die Besucher Ihrer Site sich auch ein wenig anstrengen müssen, bauen Sie zum Schluss noch eine Mischfunktion für die Puzzleteile ein, die die Teile zu Beginn in eine zufällige Reihenfolge bringt. Es gibt verschiedene Möglichkeiten, dies zu realisieren. In diesem Beispiel findet ein Austausch zweier verknüpfter Hintergrundbilder statt. Die Random-Funktion bestimmt zwei Zahlen zwischen 0 und 5, die gleichbedeutend mit den einzelnen Bildteilen ist. Sind die beiden ermittelten Zahlen z1 und z2 ungleich, dann werden die zugeordneten Hintergrundbilder ausgetauscht. Dies hat zur Folge, dass die Teile durchgemischt werden. Dazu sind ein paar Vorarbeiten notwendig. Zum Ansprechen der div-Container versehen Sie die einzelnen Elemente mit eindeutigen IDs von P0 bis P5.

Das Tauschen der Bilder ist in der Funktion change_ pics() gekapselt, die als erste Bedingung in der Funktion get_started() aufgerufen wird.
Der Zähler i markiert die Anzahl der Tauschvorgänge und hat im Beispiel einen Wert von 25. Unter Verwendung der Funktion Math.random() erzeugen Sie zwei Zufallsvariablen mit Werten zwischen 0 und 5.


z1=Math.floor(Math.random() * 6);
z2=Math.floor(Math.random() * 6);

Damit das Ausgangsbild des ersten Elements nicht verloren geht, wird es in der Variablen tmp zwischengespeichert.

tmp=document.getElementById("P"+z1).style.background;

Danach fängt der Tauschvorgang an. Der Hintergrund des zweiten Elements wird dem ersten zugewiesen. Damit nicht beim Rücktausch beide Elemente zum Schluss das gleiche Bild haben, kommt die Variable tmp zum Einsatz. Der Inhalt wird nun dem zweiten Element als neuer Hintergrund zugewiesen.


document.getElementById("P"+z1).style.background =
document.getElementById("P"+z2).style.background;
document.getElementById("P"+z2).style.background = tmp;

Dieser Vorgang wird über eine while-Schleife abhängig vom Zähler i-mal wiederholt.


Warenkorb-Funktion

Drag and Drop mit Javascript

Dank dieser Funktionalität lassen sich bestimmte Artikel auch in einen Warenkorb legen. Im letzten Beispiel erfahren Sie, wie Sie dies bewerkstelligen. Dazu gibt es drei Elemente und einen Warenkorb. Wird ein Artikel auf den Warenkorb gezogen, dann erhalten Sie eine Popup-Nachricht mit einem Hinweis. Hier lässt sich auch nach Belieben eine Weiterverarbeitung integrieren.

Alle Artikel sind mit einer ID und einem Titel verbunden. Die ID dient zur Weiterverarbeitung, wenn Sie Ihr eigenes Coding einbauen möchten. Damit Sie wissen, was der Besucher gerade im Zugriff hat, missbrauchen Sie die Eigenschaft Title. Hier ist im Beispiel der Artikelname hinterlegt.

Die Arbeit wird in der Funktion move_shop_ basket() hinterlegt, die aus stop_moving() heraus aufgerufen wird. Als Erstes ermitteln Sie, ob sich der bewegte Artikel tatsächlich im Warenkorb befindet. Hierzu wird über die Mausposition und die Grenzen des Warenkorbs ermittelt, ob der Artikel auch wirklich drin ist. Diese Überprüfung findet für die x- und die y-Koordinate statt. Nur wenn beide Prüfungen positiv ausfallen, liegt das Objekt auch wirklich im Warenkorb.


diffx = active_object.offsetLeft-150;
if(diffx>75 && diffx<700)
in_x = 1;
diffy = active_object.offsetTop-150;
if (diffy>-100 && diffy<500)
in_y=1;

Damit kein Element verloren geht, das sich schon im Warenkorb befindet, speichern Sie die Informationen rudimentär in einer globalen Variablen mit dem Namen warenkorb und geben diese zum Schluss auch aus.


if (in_x==1 && in_y==1){
if (warenkorb != null)
warenkorb = warenkorb+','+active_object.title;
else
warenkorb = active_object.title;
active_object.style.background="";
alert('Sie haben folgende Dinge im Warenkorb:'+warenkorb);

Das letzte Beispiel soll Ihnen ein paar Anregungen für weitere Einsatzgebiete geben. Die Funktion des Warenkorbs spielt hier nur eine untergeordnete Rolle – es geht hier um den Einsatz der Layer samt der Drag-and-Drop-Funktionalität. Das Ganze ist so aufgebaut, dass Sie an den passenden Stellen einfach Ihre eigenen Weiterentwicklungen einbinden können.