原生js实现div拖拽并在任意位置放下

代码

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
<style>
#main{width:100px;height:100px;background:#ffccff;position:absolute;}
</style>
<script>
/*1:拖拽的时候有文字选中会有问题;
原因:这是浏览器的默认拖拽文字的行为
解决方案:标准浏览器下:阻止默认行为,在onmousedown结尾加上return false即可
ie8及其以下版本:设置全局捕获,方法如下设置全局捕获setCapture最后释放releaseCapture*/
window.onload = function(){
var oDiv = document.getElementById("main");
var odiv = document.getElementById("div");
oDiv.onmousedown = function(ev){
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if(oDiv.setCapture){
oDiv.setCapture();
}
document.onmousemove = function(ev){
//这里为什么使用document,是因为快速拖拽的话会鼠标丢失,
var ev = ev || event;
oDiv.style.left = ev.clientX - disX+"px";
oDiv.style.top = ev.clientY - disY+"px";
}
document.onmouseup = function(ev){
document.onmousemove = document.onmouseup = null;
//为何不用oDiv.onmouseup是因为被挡住之后会无视掉遮挡的元素
if(oDiv.releaseCapture){
oDiv.releaseCapture();
}
}
return false;
}
}
var aaa = function(){document.getElementById('aaa').style.display='block';}
</script>
<body>
<div id="main"></div>
</body>

关于SetCapture()函数

定义:该函数属于当前线程的指定窗口里设置鼠标捕获。一旦窗口捕获了鼠标,所有鼠标输入都针对该窗口,无论光标是否在窗口的边界内。同一时刻只能有一个窗口捕获鼠标。如果鼠标光标在另一个线程创建的窗口上,只有当鼠标键按下时系统才将鼠标输入指向指定的窗口。
大概作用就是在拖动过程中,可以捕获到浏览器的外的拖动事件。
要注意的是,在浏览器外无法捕获到鼠标的点击事件,因为鼠标点击后焦点就在浏览器外的窗口了,原来的SerCapture函数就失效了。

关于releaseCapture()函数

SetCapture()与releaseCapture()成对出现,否则别的线程调用就会失败。

关于offsetLeft

运用这段代码时出现了错误,反复调用控制台发现offsetLeft并非是元素到浏览器左边的距离,而是元素到第一个最近的定位过的父元素(offsetParent)的距离。如果没有定位过的父元素,则offsetParent为body。