Werbung einblenden Werbung ausblenden


Home / Tutorials / JavaScript Handbuch / drag and drop


drag and drop

drag and drop

Einer der "spektakulärsten" Effekte, die man mit DHTML produzieren kann, ist drag and drop, das heisst die Möglichkeit, irgendein x-beliebiges Element einer HTML Seite zu packen und irgendwo hinzusetzen. Wenn man diesen Effekt ohne weiteres cross browser compatibel programmieren könnte, gäbe es sicher auch schon einige Anwendungen, vor allem Spiele, die diesen Effekt einsetzen. Allmählich nähern sich Netscape und Explorer im Hinblick auf DHTML einander an, so dass man diesem Effekt wohl öfter im Netz begegnen wird. Möglich wäre es zum Beispiel ein Puzzle wie das unten stehende zu kreieren, das der User dann via drag and drop zu einem Bild zusammenbauen kann.

 

 

 

 

 

 

 

 

 

Alles klar ? Wenn wir über einem Bild die rechte Maustaste drücken "packen" wir das Bild und können es bei gedrückter Maustaste über den Bildschirm ziehen. Lassen wir die Maustaste los, ist das Bild wieder frei. So können wir das Puzzel zusammenbauen. Der Skript, der uns das produziert, sieht so aus.

<html>
<head>
<title>drag and drop</title>

<script language="JavaScript">

document.onmousedown=packmich;
document.onmouseup=beenden;
ganzoben=1;
function packmich(e)
{
if(!document.all)
{
objekt=e.target.id;
}
else
{
objekt=event.srcElement.id;
}

if(objekt)
{
if(!document.all)
{event=e;}
startX=event.clientX;
startY=event.clientY;

document.getElementById(objekt).style.zIndex=ganzoben;
ganzoben++;

XpositionAlt=document.getElementById(objekt).style.left;
YpositionAlt=document.getElementById(objekt).style.top;
document.onmousemove=bewegen;
return false;
}
}
function bewegen(e)
{
if(objekt)
{
if(!document.all)
{event=e;}
Xwert=event.clientX-startX;
Ywert=event.clientY-startY;


document.getElementById(objekt).style.left=parseInt(XpositionAlt)+Xwert;
document.getElementById(objekt).style.top=parseInt(YpositionAlt)+Ywert;

}
return false;
}
function beenden()
{
objekt=false;
}

</script>

</head>


<body>
<img src=beispiele/puzzle/1.gif id="1" style="position:absolute;top:160;left:20">
<img src=beispiele/puzzle/2.gif id="2" style="position:absolute;top:160;left:320">
<img src=beispiele/puzzle/3.gif id="3" style="position:absolute;top:160;left:620">
<img src=beispiele/puzzle/4.gif id="4" style="position:absolute;top:380;left:20">
<img src=beispiele/puzzle/5.gif id="5" style="position:absolute;top:380;left:320">
<img src=beispiele/puzzle/6.gif id="6" style="position:absolute;top:380;left:620">
</body>
</html>

Unter Umständen erleichtert es jetzt das Verständnis, wenn man sich das unter dynamic html Gesagte nochmal in Erinnerung ruft. Gehen wir den Skript Schritt für Schritt durch. Zu Beginn haben wir

document.onmousedown=packmich;
document.onmouseup=beenden;

Das heisst, wir definieren für das gesamte Dokument, dass bei onmousedown die Funktion packmich() aufgerufen wird und bei onmouseup die Funktion beenden. Man muss jetzt sehen, dass wir für onmousemove erstmal nichts definieren, da wir ja nicht wollen, dass die Bilder immer der Maus hinterlaufen. Wir wollen, dass die Bilder nur dann der Maus hinterherlaufen, wenn der User die Maustaste gedrückt hält. Wir wollen des weiteren auch nicht, dass jedes Element verschoben werden kann, wir wollen nur zulassen, dass die Bilder verschoben werden können. Wir müssen also in der Funktion packmich() dafür sorgen, dass der even handler onmousemove, der die Funktion bewegen() aufruft, nur dann aktiv ist, wenn erstens die Maustaste gedrückt ist und sich zweitens die Maus über einem der Bilder befindet befindet. Schauen wir uns also die Funktion packmich() genauer an.

function packmich(e)
{
if(!document.all)
{
objekt=e.target.id;
}
else
{
objekt=event.srcElement.id;
}
if(objekt)
{
if(!document.all)
{event=e;}
startX=event.clientX;
startY=event.clientY;
XpositionAlt=document.getElementById(objekt).style.left;
YpositionAlt=document.getElementById(objekt).style.top;
document.onmousemove=bewegen;
return false;
}
}

Nochmal. Die Funktion packmich() wird immer aufgerufen, wenn der User irgendwo auf der Seite die Maustaste drückt. Innerhalb der Funktion wird dann aber entschieden, ob dann auch tatsächlich etwas passiert. Wir interessieren uns jetzt für die id des Objektes, über dem die Maustaste gedrückt wurde. Obwohl sich die Konzepte des Internet Explorers und von Netscape 6+ angenähert haben, sind sie doch noch nicht ganz identisch. Wird mit

document.onmousedown=packmich;

eine Funktion aufgerufen, haben wir schon einen Unterschied. Beide Browser speichern alle Informationen zu einem Event in einem Objekt. Beim Explorer allerdings ist diese Objekt als globale Variable überall vorhanden, während Netscape dieses Event Objekt als Parameter übergibt. Das ist aber leider nicht der einzige Unterschied. Auch die Art und Weise, wie man die Kindobjekte und die Eigenschaften unterhalb des Event Objektes anspricht, unterscheidet sich. Wir wollen wissen, welche id das Objekt hat, über dem die Maus gedrückt wurde, weil wir ja nachher dieses und kein anderes Objekt bewegen wollen. Dies ermitten wir bei Netscape mit

objekt=e.target.id;
und beim Internet Explorer mit
objekt=event.srcElement.id;

Als nächstes wollen wir noch wissen, wo auf die Maustaste gedrückt wurde, denn dies wird es uns später erlauben, zu ermitteln, um wieviel die Maus bewegt wurde. Allerdings interessiert uns das nur, wenn das Objekt vorhanden ist, denn sonst wollen wir ja nix bewegen. Die Variable Objekt hat aber nur dann einen Inhalt, wenn auf etwas geklickt wurde, was eine id hat. Wir machen also alle folgenden Befehle von der Frage abhängig, ob die Variable Objekt einen Inhalt hat ( irgendein Inhalt ist in der Perl Logik mit true identisch.) Als nächstes sorgen wir noch dafür, dass das Element, dass wir angeclickt haben, das oberste ist, also nicht von einem anderen Bild verdeckt wird, wenn wir es über ein anderes Bild schieben. Wir haben am Anfang die Variable ganzoben mit dem Wert 1 initialisiert. Jedesmal, wenn wir über einem Bild die Maustaste drücken, erhöhen wir diesen Wert. Dann weisen wir diesem Wert dem zIndex zu, der angibt, wo sich das entsprechende Objekt in der Hierarchie befindet. Da ganzoben ja immer um eins erhöht wird, ist das angeklickte Element das höchste.

document.getElementById(objekt).style.zIndex=ganzoben;
ganzoben++;

Das mit dem zIndex ist wohl das, was man quick and dirty programming nennt. Es hat aber den unbestechlichen Charme, dass es funktionniert. Sehen wir einmal von der Tatsache ab, dass das Event Objekt in Netscape als Parameter übergeben wird und im Explorer als globale Variable event überall vorhanden ist, ist die Syntax gleich. Wir weisen event den Wert e zu und können dann die Position des Mauszeigers zum Zeitpunkt des events ermitteln.

if(!document.all)
{event=e;}

startX=event.clientX; startY=event.clientY; Kurz noch eine Bemerkung zu document.all. document.all braucht man nicht mehr, da jetzt getElementById, getElementsByName etc. zur Verfügung steht. Nach wir vor hat der Explorer dieses Objekt, das alle Elemente eines documentes beinhaltet. Wenn also ein Browser !document.all nicht hat, dann ist es auf jeden Fall nicht der Explorer. Jetzt haben wir erstmal alles, was wir brauchen. Wir kennen das Objekt, über dem die Maus gedrückt wurde und wir kennen die Position des Mauszeigers, als die Maustaste gedrückt wurde. Da wir es folglich mit einer Situation zu tun haben, wo wir etwas bewegen wollen, schieben wir mit

document.onmousemove=bewegen;

die Funktion bewegen an. Vorher ermitteln wir noch, wo das Bild, das wir verschieben wollen, im Moment positionniert ist, denn auch das werden wir nachher brauchen.

XpositionAlt=document.getElementById(objekt).style.left;
YpositionAlt=document.getElementById(objekt).style.top;

Die Funktion bewegen sieht dann so aus.

function bewegen(e)
{
if(objekt)
{
if(!document.all)
{event=e;}
Xwert=event.clientX-startX;
Ywert=event.clientY-startY;
document.getElementById(objekt).style.left=parseInt(XpositionAlt)+Xwert;
document.getElementById(objekt).style.top=parseInt(YpositionAlt)+Ywert;
}
return false;
}

Die Funktion bewegen() tut nur etwas, wenn ein Objekt vorhanden ist, das heisst, wenn der User mal über einem Bild die Maustaste gedrückt hat, siehe oben. Wir müssen alle Funktionalitäten der Funktion bewegen() kapseln, da wir eine Möglichkeit brauchen, den Vorgang zu stoppen. Wir tun das nachher in der Funktion beenden(), die die Variable objekt wieder auf false setzt. Aus den oben bereits erwähnten Gründen, muss zuerst der Wert der Variablen e der Variablen event zugewiesen werden.

if(!document.all)
{event=e;}

Anschliessend ermitteln wir um wieviel der Mauszeiger bewegt wurde.

Xwert=event.clientX-startX;
Ywert=event.clientY-startY;

event.clientX ist hierbei der horizontale Abstand zum rechten Rand des Dokumentes, event.ClientY der horizontale. Von diesen Werten ziehen wir die Werte ab, die wir hatten, als das Event ausgelöst wurde und haben dann die Strecke, die der Mauszeiger zurückgelegt hat. Die neue Position des Bildes ergibt sich aus der alten Position des Bildes + der Differenz.

document.getElementById(objekt).style.left=parseInt(XpositionAlt)+Xwert;
document.getElementById(objekt).style.top=parseInt(YpositionAlt)+Ywert;

Wenn wir die Maustaste loslassen, lösen wir die Funktion beenden aus. Wir erinnern uns, der event handler onmouseup ist im ganzen Dokument aktiv, wir hatten zu Beginn

document.onmouseup=beenden;

Die Funktion beenden() tut nicht viel, sie weist lediglich der Variablen objekt einen neuen Wert zu, nämlich false, was dann bewirkt, dass die Funktion bewegen() zwar noch aktiv ist, aber nichts mehr tut, so dass wir mit der Funktion beenden() das Verschieben des Objektes stoppen können.

vorhergehendes Kapitel