Drag&Drop: Browser-Unterschiede bei onmousemove?
parseHint("Pro")
- javascript
Hallo,
folgendes Problem mit meinem drag&drop-Script:
-> anscheinend werden bei FF mehr Maus-Bewegungen registriert als bei IE (?)
Ich habe eine div, darin das Bild eines Dia-Streifens (vertikal), wobei die
div einen niedrigeren height-Wert hat als das Bild (-> overflow: hidden;).
Über der div (also höherer z-index) liegt ein Bild von einem Dia-Rahmen.
Nun soll man mit drag&drop den Dia-Rahmen über den Dia-Streifen "schieben",
wobei in einem anderen Bereich immer das Bild zu sehen sein soll, über dessen
Dia-Streifen-Abschnitt sich gerade der Dia-Rahmen befindet.
Wenn der Rahmen an die obere bzw. untere Kante der div kommt, so soll das
Dia-Streifen-Bild entsprechend nach unten bzw. oben verschoben werden.
eine kl. Skizze:
-------
| [1] | -> [1] dies ist der Streifen (in dem die Bilder 1-6 zu
| [2] | [2] sehen sind (wobei es sich aber nur um ein image
|{[3]}| ... handelt
| [4] |
------- der gestrichelte Rahmen ist die div,
[5] { } ist das Dia-Rahmen-Bild
[6]
der (vereinfachte) HTML-Schnippsel hierzu sieht so aus:
<div><img src="bilder/diastrip.png" id="strip" /></div>
<div onmousedown="javascript:dragStart(this)"><img src="bilder/diarahmen.png" /></div>
<div id="bildbox"><img src="bilder/strip1.jpg" /></div>
das script:
function IDy(id) {
return document.getElementById(id).style;
}
function ID(id) {
return document.getElementById(id);
}
var dragObjekt = false;
var dragX = 0;
var dragY = 0;
var posX = 0;
var posY = 0;
var stripY;
document.onmousemove = drag;
document.onmouseup = new Function("dragObjekt=false");
document.onmousedown = new Function("return false");
function dragStart(element) {
dragObjekt = element;
dragX = posX - dragObjekt.offsetLeft;
dragY = posY - dragObjekt.offsetTop;
}
function drag(e) {
posX = document.all ? window.event.clientX : e.pageX;
posY = document.all ? window.event.clientY : e.pageY;
stripY = parseInt(IDy('strip').top);
if (dragObjekt != false) {
// 116 = Oberkante der div; 477 = Unterkante der div minus height des Rahmens
if ((posY - dragY) > 116 && (posY - dragY) < 477) {
dragObjekt.style.top = (posY - dragY) + "px";
}
else if ((posY - dragY) <= 116) {
dragObjekt.style.top = "116px";
stripDown();
}
else if ((posY - dragY) >= 477) {
dragObjekt.style.top = "477px";
stripUp();
}
// auf dem Streifen sind 10 Bildchen zu sehen, je von einer height von ca 52px
var stripMapTop = new Array(472, 420, 367, 315, 262, 210, 157, 105, 52, 0);
var stripMapBottom = new Array(523, 471, 419, 366, 314, 261, 209, 156, 104, 51);
var bild = ID('bildbox');
for (i=0; i<10; i++) {
if ((dragObjekt.offsetTop - 120) >= (stripMapTop[i] + stripY - 25) &&
(dragObjekt.offsetTop - 120) <= (stripMapBottom[i] + stripY - 25)) {
bild.src = imgs[i].src;
}
}
return false;
}
}
function stripDown() {
if (dragObjekt == false) {return;}
stripY = parseInt(IDy('strip').top);
if (stripY < 0) {
IDy('strip').top = stripY + 1 + 'px';
setTimeout('stripDown()', 10);
}
}
function stripUp() {
if (dragObjekt == false) {return;}
stripY = parseInt(IDy('strip').top);
if (stripY > -103) {
IDy('strip').top = stripY - 1 + 'px';
setTimeout('stripUp()', 10);
}
}
var imgs = new Array();
function preloadImgs() {
for (i=0;i<10;i++) {
imgs[i] = new Image();
imgs[i].src = "bilder/strip"+(i+1)+".jpg";
}
}
preloadImgs();
Bestimmt ist der Weg, wie ich über stripUp()/Down() die vertikale Bewegung
des Dia-Streifens handle, sehr stümperhaft - bin noch js-Anfäger...
Wenn mir jemand sagen kann, wie ich
(1) einen besseren Lösungsweg dafür finde, das Streifen-Bild zu bewegen,
wenn der Rahmen die obere/untere Kante der div erreicht, und/oder
(2) es bewerkstellige, dass sich der Streife in allen Browsern
gleichschnell bewegt, und/oder
(3) es erreichen kann, dass die Funktion drag() es sofort "schnallt", wenn
sich durch stripUp()/Down() die top-Koordinate des Streifen-Bildes ver-
ändert hat und dementsprechend mit dem Anzeigen des nun unter dem Rahmen-
Bildes befindlichen Bildchens in der "bildbox" reagiert,
dann wäre ich sehr, sehr dankbar!
Bin mal gespannt, ob sich überhaupt jemand durch diese Nachricht gewühlt hat :D
lieben Gruß
Hallo nochmal,
ich befürchte, mein Posting war zu wirr oder zu lang :-(
ich will hier jetzt nicht pushen, sondern meinen Fragen-Komplex abspecken
und einfach nur wissen, ob mir jemand sagen kann, was ich machen muss,
damit sich das drag-Objekt exakt in einem definierten Bereich draggen lässt -
und nicht etwa ab und zu nur bis 5px vor den Rand.
Hat das etwas mit der Schnelligkeit der Mausbewegung zu tun? Z.B., dass
vielleicht onmousemove aufhört zu feuern, wenn der Cursor für kurze Zeit nicht
über dem drag-Objekt ist?
Und weiß jemand, wieso ich, wenn ich mir die Offset-Positionen des drag-Objektes
in eine Tabelle schreiben lasse, von FF wesentlich mehr Einträge als von IE
bekomme?
Vielen Dank im Voraus für Deine Antwort!
Lieben Gruß
ich befürchte, mein Posting war zu wirr oder zu lang :-(
z.T. ja. Die Beschreibung ist schwer nachvollziebar und ich müßte sie jetzt mehrmals lesen um zu verstehen, was dein Problem sein könnte, wozu ich aber ehrlich gesagt nicht viel Lust habe.
Einfacher wäre es, wenn du eine Beispielseite bauen würdest, wo man das Problem nachvollziehen kann.
Struppi.
ich befürchte, mein Posting war zu wirr oder zu lang :-(
z.T. ja. Die Beschreibung ist schwer nachvollziebar und ich müßte sie jetzt mehrmals lesen um zu verstehen, was dein Problem sein könnte, wozu ich aber ehrlich gesagt nicht viel Lust habe.
Einfacher wäre es, wenn du eine Beispielseite bauen würdest, wo man das Problem nachvollziehen kann.
Struppi.
Hallo Struppi,
danke Dir für Deine Antwort!
Habe jetzt eine Beispielseite gebaut. Den Code kann man, so wie er ist,
komplett übernehmen, um sich die Sache anzuschauen. Habe alles etwas ver-
einfacht: keine Bilder, nur divs; statt beim draggen .src von Bildern zu ändern,
ändert sich hier die background-color (eine Farbe entspricht in meinem eigentlichen
Code einem Abschnitt des Dia-Streifen-images).
das Javascript habe ich seit gestern schon abgeändert, s.d. es jetzt einiger-
maßen funktioniert - auch wenn es wahrscheinlich alles andere als gut
geschrieben ist...
hier die Beispielseite:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/transitional.dtd">
<html><head><title>Bildauswahl durch drag-drop</title>
<script type="text/javascript">
function IDy(id) {
return document.getElementById(id).style;
}
function ID(id) {
return document.getElementById(id);
}
var dragObjekt = false;
var dragY = 0;
var posY = 0;
var stripY;
var aktuellePos;
var stripDownBusy = false;
var stripUpBusy = false;
document.onmousemove = drag;
document.onmouseup = new Function("dragObjekt=false");
document.onmousedown = new Function("return false"); // FF-internes D&D unterbinden
function dragStart(element) {
dragObjekt = element;
dragY = posY - dragObjekt.offsetTop;
}
function drag(e) {
posY = document.all ? (window.event.clientY + document.body.scrollTop - document.body.clientTop) : e.pageY;
stripY = ID('diaStrip').offsetTop;
if (dragObjekt != false) {
if ((posY - dragY) > 50 && (posY - dragY) < 200) {
dragObjekt.style.top = (posY - dragY) + "px";
}
else if ((posY - dragY) <= 50) {
dragObjekt.style.top = "50px";
if (stripDownBusy == false) {
stripDown();
}
}
else if ((posY - dragY) >= 200) {
dragObjekt.style.top = "200px";
if (stripUpBusy == false) {
stripUp();
}
}
aktuellePos = posY - dragY;
aktualisiereBild();
return false;
}
}
function aktualisiereBild() {
var stripMapTop = new Array(0, 100, 200, 300);
var stripMapBottom = new Array(100, 200, 300, 400);
var bgColors = new Array("blue", "green", "yellow", "orange");
var bild = IDy('bildBox');
for (i=0; i<4; i++) {
if ((dragObjekt.offsetTop - 50) >= (stripMapTop[i] + stripY - 40) && (dragObjekt.offsetTop - 50) <= (stripMapBottom[i] + stripY - 40)) {
bild.backgroundColor = bgColors[i];
}
}
}
function stripDown() {
stripDownBusy = true;
if (dragObjekt == false) {
stripDownBusy = false;
return;
}
stripY = ID('diaStrip').offsetTop;
if (stripY < 0 && aktuellePos <= 50) {
IDy('diaStrip').top = stripY + 2 + 'px';
aktualisiereBild();
setTimeout('stripDown()', 1);
}
else {stripDownBusy = false;}
}
function stripUp() {
stripUpBusy = true;
if (dragObjekt == false) {
stripUpBusy = false;
return;
}
stripY = ID('diaStrip').offsetTop;
if (stripY > -150 && aktuellePos >= 200) {
IDy('diaStrip').top = stripY - 2 + 'px';
aktualisiereBild();
setTimeout('stripUp()', 1);
}
else {stripUpBusy = false;}
}
/*
var imgs = new Array();
function preloadImgs() {
for (i=0;i<10;i++) {
imgs[i] = new Image();
imgs[i].src = "bilder/strip"+(i+1)+".jpg";
}
}
preloadImgs();*/
</script>
<style type="text/css">
#diaStripBox {position: absolute; top: 50px; left: 50px; width: 100px; height: 250px; overflow: hidden; border: 1px solid black;}
#diaStrip {position: absolute; top: 0px; left: 0px; width: 100px; height: 500px;}
#abschnitt1 {height: 100px; background-color: blue;}
#abschnitt2 {height: 100px; background-color: green;}
#abschnitt3 {height: 100px; background-color: yellow;}
#abschnitt4 {height: 100px; background-color: orange;}
#diaRahmen {position: absolute; top: 170px; left: 45px; width: 110px; height: 100px; border: 3px solid grey; cursor: move; z-index: 2;}
#bildBox {position: absolute; top: 50px; left: 250px; width: 300px; height: 300px; border: 3px solid black; background-color: green;}
</style>
</head><body>
<div id="diaStripBox">
<div id="diaStrip">
<div id="abschnitt1"></div>
<div id="abschnitt2"></div>
<div id="abschnitt3"></div>
<div id="abschnitt4"></div>
</div>
</div>
<div id="diaRahmen" onmousedown="javascript:dragStart(this)"></div>
<div id="bildBox"></div>
</body></html>
Liebe(r) parseHint("Pro"),
Habe alles etwas ver-
einfacht: keine Bilder, nur divs; statt beim draggen .src von Bildern zu
ändern, ändert sich hier die background-color (eine Farbe entspricht in
meinem eigentlichen Code einem Abschnitt des Dia-Streifen-images).
damit hast Du aber die Problemstellung entscheidend verändert! Die Browser bieten bei Bildern ein zusätzliches Drag&Drop-Verhalten an, welches bei <div>-Elementen so nicht einsetzt. Oder kannst Du (ohne vorheriges Markieren!) durch einfaches Drag&Drop den Inhalt eines <div>-Elements aus dem Browser in ein Verzeichnis (z.B. Desktop) kopieren?
Um das browserseitige Drag&Drop bei Grafiken zu deaktivieren braucht es ein paar Tricks. Ich verwende folgende Funktion, um (im IE) dieses "Extra-Drag&Drop" zu unterbinden:
Quiz.antiMarkierungsModusFuerIE = function (schalter) {
if (schalter) {
// Anti-Markierungs-Effekt für IE einschalten
Quiz.oldDocOnSelectStart = window.document.onselectstart;
Quiz.oldDocOnDragStart = window.document.ondragstart;
window.document.onselectstart = function () { return false;};
window.document.ondragstart = function () { return false;};
} else {
// Anti-Markier-Effekt für IE beenden
if (Quiz.oldDocOnSelectStart || typeof(window.document.onselectstart) == "function")
window.document.onselectstart = Quiz.oldDocOnSelectStart;
if (Quiz.oldDocOnDragStart || typeof(window.document.ondragstart) == "function")
window.document.ondragstart = Quiz.oldDocOnDragStart;
}
};
Obige Funktion ist aus meinem Quiz-Framework entnommen, daher das globale Quiz-Objekt. Du kannst es aber anders machen...
Liebe Grüße,
Felix Riesterer.
damit hast Du aber die Problemstellung entscheidend verändert
Lieber Felix,
ich danke Dir sehr für Deine Antwort.
Die Beispielseite sollte nur der Veranschaulichung dienen, damit jemand (z.B.
Struppi) sich das kopieren und auf seinem Browser laufen lassen kann. Hierbei
kam es darauf an, zu zeigen, was ich mit dem wechselseitgen Verhalten der
Funktionen drag() und stripUp()/Down() meinte.
Dass es da so einige Problemchen gibt, wenn man z.B. Bilder in einer div
draggen will, hatte ich bemerkt, und ich freue mich über den Codeschnippsel von
Dir, den ich auch gleich einsetzen werden :-}
Im Großen und Ganzen erfüllt mittlerweile mein Script seine Zwecke - auch wenn
mir professionellere Methoden lieber gewesen wären - ist jetzt halt alles etwas
stümperhaft zusammengekleistert; insbesondere die Regulierung des Zusammenspiels
der drag- und der strip-Funktionen mittels der Variablen stripUpBusy bzw.
stripDownBusy.
Außerdem verstehe ich immer noch nicht ganz, warum die Funktion drag() bei
FF anscheinend öfter durchlaufen wird als bei IE.
Aber besser ein funktionierendes Noobie-Script als ein nicht
funktionierender Profi-Script-Versuch ;}
Liebe Grüße und danke für Deine Hilfe,
(der) parseHint("pro")