拖拽
位置信息
- clientX / clientY 获取距离可视区域的距离;
- pageX / pageY 获取距离文档的(没有滚动条的时候与client一样);
- screenX / screenY 获取距离屏幕 (指的电脑屏幕);
拖拽涉及到的事件
- 按下:onmousedown
- 移动:onmousemove
- 抬起:onmouseup
拖拽的实现
- 找到一个固定值(不变的点)=>鼠标距离拖拽元素的距离(因为按下拖动的时候这个距离不变)。
- 获取拖拽后元素距离body的距离 (offset不行)
第一版代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <style> * { padding: 0; margin: 0; }
.box { width: 100px; height: 100px; background-color: red; position: absolute; left: 0; top: 0; } </style>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
const box = document.getElementsByClassName("box")[0];
box.onmousedown = function (ev) { ev = ev || window.event; const x = ev.clientX - box.offsetLeft; const y = ev.clientY - box.offsetTop;
box.onmousemove = function (ev) { ev = ev || window.event; const left = ev.clientX - x; const top = ev.clientY - y; box.style.left = left + "px"; box.style.top = top + "px"; }
box.onmouseup = function () { box.onmousemove = null; box.onmouseup = null; }
}
|
bug:鼠标移动过快,鼠标可能会离开div(box),进而到文档上。
第二版代码
将鼠标移动和抬起的对象设置为了整个屏幕,别的未修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
const box = document.getElementsByClassName("box")[0];
box.onmousedown = function (ev) { ev = ev || window.event; const x = ev.clientX - box.offsetLeft; const y = ev.clientY - box.offsetTop;
window.onmousemove = function (ev) { ev = ev || window.event; const left = ev.clientX - x; const top = ev.clientY - y; box.style.left = left + "px"; box.style.top = top + "px"; }
window.onmouseup = function () { window.onmousemove = null; window.onmouseup = null; }
}
|
如上代码也可以使用getBoundingClientRect()
获取dom位置
1 2 3 4 5 6 7
| ev = ev || window.event;
const boxLocation = box.getBoundingClientRect();
const x = ev.clientX - boxLocation.left; const y = ev.clientY - boxLocation.top;
|
bug:能超出屏幕范围。
第三版代码
限制边界,别的未修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
const box = document.getElementsByClassName("box")[0];
box.onmousedown = function (ev) { ev = ev || window.event; const boxLocation = box.getBoundingClientRect(); const x = ev.clientX - boxLocation.left; const y = ev.clientY - boxLocation.top;
const minLeft = 0 const minTop = 0; const maxLeft = document.documentElement.clientWidth-box.offsetWidth; const maxTop = document.documentElement.clientHeight-box.offsetHeight;
window.onmousemove = function (ev) { ev = ev || window.event; let left = ev.clientX - x; let top = ev.clientY - y; if(left<minLeft){ left=minLeft }else if(left>maxLeft){ left=maxLeft };
if(top<minTop){ top=minTop }else if(top>maxTop){ top=maxTop };
box.style.left = left + "px"; box.style.top = top + "px"; }
window.onmouseup = function () { window.onmousemove = null; window.onmouseup = null; }
}
|
bug:当div里面有图片或者文字的时候,会有默认行为。
最终代码
在鼠标按下里增加了阻止默认行为。
1 2
| ev.preventDafault?ev.preventDafault():ev.returnValue=false;
|
拖拽自动回放
设置一个数组用来存放坐标,每次通过pop()将末尾的值赋值给拖拽元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
var box = document.getElementsByClassName("box")[0]; var btn = document.getElementsByClassName("btn")[0];
var stepArr = []
box.onmousedown = function (ev) { ev = ev || window.event; stepArr.push({ left: parseFloat(window.getComputedStyle(box).left), top: parseFloat(window.getComputedStyle(box).top) }) ev.preventDafault?ev.preventDafault():ev.returnValue=false; var x = ev.clientX - box.offsetLeft; var y = ev.clientY - box.offsetTop;
document.onmousemove = function (ev) { ev = ev || window.event; var left = ev.clientX - x; var top = ev.clientY - y; var minLeft = 0, maxLeft = document.documentElement.clientWidth - box.clientWidth; var minTop = 0, maxTop = document.documentElement.clientHeight - box.clientHeight; if (left <= minLeft) { left = minLeft; } else if (left >= maxLeft) { left = maxLeft; } if (top <= minTop) { top = minTop; } else if (top >= maxTop) { top = maxTop; } box.style.left = left + "px"; box.style.top = top + "px"; stepArr.push({ "left": left }, { "top": top }) } }
document.onmouseup = function () { document.onmousemove = null; }
btn.onclick = function () { window.clearInterval(this.timer); var that = this; this.timer = window.setInterval(function () { var curStep = stepArr.pop(); if (stepArr.length <= 0) { box.style.left = curStep.left + "px"; box.style.top = curStep.top + "px"; window.clearInterval(that.timer); } else { box.style.left = curStep.left + "px"; box.style.top = curStep.top + "px"; } }, 10) }
|