Ответ 1
ОК, здесь мой личный код, который я использую для облегченных развертываний (проекты, в которых использование библиотеки либо запрещено, либо переполняют по какой-либо причине). Во-первых, я всегда использую эту функцию удобства, чтобы передать либо id, либо фактический элемент dom:
function get (el) {
if (typeof el == 'string') return document.getElementById(el);
return el;
}
В качестве бонуса get()
короче, чем document.getElementById()
, а мой код заканчивается короче.
Второе понимание того, что делают большинство библиотек, - это совместимость между браузерами. Если все браузеры ведут себя одинаково, код довольно тривиален. Поэтому давайте напишем некоторые кросс-браузерные функции, чтобы получить положение мыши:
function mouseX (e) {
if (e.pageX) {
return e.pageX;
}
if (e.clientX) {
return e.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
}
return null;
}
function mouseY (e) {
if (e.pageY) {
return e.pageY;
}
if (e.clientY) {
return e.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
}
return null;
}
ОК, две приведенные выше функции идентичны. Есть, конечно, лучшие способы написать их, но я сохраняю это (относительно) просто на данный момент.
Теперь мы можем написать код перетаскивания. То, что мне нравится в этом коде, - это то, что все захвачено в одном закрытии, поэтому нет глобальных переменных или вспомогательных функций, засоряющих браузер. Кроме того, код отделяет дескриптор перетаскивания от объекта, который перетаскивается. Это полезно для создания диалоговых окон и т.д. Но если не нужно, вы всегда можете назначить им один и тот же объект. В любом случае, здесь код:
function dragable (clickEl,dragEl) {
var p = get(clickEl);
var t = get(dragEl);
var drag = false;
offsetX = 0;
offsetY = 0;
var mousemoveTemp = null;
if (t) {
var move = function (x,y) {
t.style.left = (parseInt(t.style.left)+x) + "px";
t.style.top = (parseInt(t.style.top) +y) + "px";
}
var mouseMoveHandler = function (e) {
e = e || window.event;
if(!drag){return true};
var x = mouseX(e);
var y = mouseY(e);
if (x != offsetX || y != offsetY) {
move(x-offsetX,y-offsetY);
offsetX = x;
offsetY = y;
}
return false;
}
var start_drag = function (e) {
e = e || window.event;
offsetX=mouseX(e);
offsetY=mouseY(e);
drag=true; // basically we're using this to detect dragging
// save any previous mousemove event handler:
if (document.body.onmousemove) {
mousemoveTemp = document.body.onmousemove;
}
document.body.onmousemove = mouseMoveHandler;
return false;
}
var stop_drag = function () {
drag=false;
// restore previous mousemove event handler if necessary:
if (mousemoveTemp) {
document.body.onmousemove = mousemoveTemp;
mousemoveTemp = null;
}
return false;
}
p.onmousedown = start_drag;
p.onmouseup = stop_drag;
}
}
Есть причина для слегка запутанных расчетов offsetX/offsetY
. Если вы заметили, это просто занимает разницу между позициями мыши и добавляет их обратно в положение перетаскивания div. Почему бы просто не использовать позиции мыши? Ну, если вы сделаете это, div перейдет к указателю мыши, когда вы нажмете на него. Какое поведение я не хотел.