HTML5现在已经有了拖放的API,也就是说拖放已经成为了HTML5的标准,不过还是先了解一下JavaScript最原始的拖拽原理。
一、拖拽的基本原理
拖拽是基于三个事件触发的:
onmousedown : 选择元素
onmousemove : 移动元素
onmouseup : 释放元素
oDiv.onmousedown = function (ev) { var ev= ev || event; // 获取到鼠标点击的时候到对象边缘的偏移值 var disX = ev.clientX - this.offsetLeft; var disY = ev.clientY - this.offsetTop; document.onmousemove = function (ev) { var ev= ev || event; // 对象的坐标就是鼠标坐标减去点击时候的偏移值。 oDiv.style.left = ev.clientX - disX + "px"; oDiv.style.top = ev.clientY - disY + "px"; } document.onmouseup = function () { document.onmousemove = document.onmouseup = null; } return false; }
1、onmousedown:模拟开始拖拽事件。
鼠标按键按下即发生 onmousedown 事件。
获取鼠标位置,获取被拖拽元素的位置,记录两者之间的纵横坐标的差值。
2、对 document 元素绑定 onmousemove,onmouseup 事件。
为什么是对 document 绑定而不是对被拖动的元素绑定呢?
原因是如果对被拖动元素绑定的话,当鼠标拖动过快时,会导致鼠标与被拖动元素的脱离。
onmousemove:模拟拖拽中事件。
鼠标拖动即发生 onmousemove 事件。
将被拖拽元素的 position 改成absolute绝对位置,这个可以通过 left 和 top 改变该元素的位置,从而使得该元素随着鼠标的拖拽而移动。
3、onmouseup:模拟拖拽结束事件。
鼠标按键弹起即发生 onmouseup 事件。可以回收 onmousemove 和 onmousedown中的事件和变量,一次拖拽至此结束。
二、兼容性问题
如果拖拽对象上面有文字,或者文档中有别的文字或者图片被选中,会触发默认的拖拽行为。
解决方法:
标准:阻止默认行为
非标准ie:全局捕获
oDiv.onmousedown = function (ev) { var ev = ev || event; var disX = ev.clientX - this.offsetLeft; var disY = ev.clientY - this.offsetTop; // 为非标准的IE设置全局捕获,给一个元素设置全局捕获以后,那么这个元素就会监听后续发生的所有事件,当有事件发生的时候,就会被当前设置了全局捕获的元素所触发。 if (oDiv.setCapture) { oDiv.setCapture(); } document.onmousemove = function (ev) { var ev = ev || event; oDiv.style.left = ev.clientX - disX + "px"; oDiv.style.top = ev.clientY - disY + "px"; } document.onmouseup = function () { document.onmousemove = document.onmouseup = null; //释放全局捕获 releaseCapture(); if (oDiv.releaseCapture) { oDiv.releaseCapture(); } } return false; }
三、拖拽的封装
var oDiv = document.getElementById('div1'); var oImg = document.getElementById('img1'); drag(oImg); drag(oDiv); function drag(obj) { obj.onmousedown = function(ev) { var ev = ev || event; var disX = ev.clientX - this.offsetLeft; var disY = ev.clientY - this.offsetTop; if ( obj.setCapture ) { obj.setCapture(); } document.onmousemove = function(ev) { var ev = ev || event; obj.style.left = ev.clientX - disX + 'px'; obj.style.top = ev.clientY - disY + 'px'; } document.onmouseup = function() { document.onmousemove = document.onmouseup = null; if ( obj.releaseCapture ) { obj.releaseCapture(); } } return false; } }
四、拖拽的范围限制
只需要实时计算拖拽的元素左、上边框距离左、上屏幕之间的距离就行了。如果把L和T的临界值L<0改成比如L<100,则可以实现磁性吸附的效果。
document.onmousemove = function (ev) { var ev = ev || event; // 获取元素拖拽中左边框距离可视区左边的距离。 var L = ev.clientX - disX; // 获取元素拖拽中上边框距离可视区上边的距离。 var T = ev.clientY - disY; if (L < 0) { L = 0; } else if (L > document.documentElement.clientWidth - obj.offsetWidth) { L = document.documentElement.clientWidth - obj.offsetWidth; } if (T < 0) { T = 0; } else if (T > document.documentElement.clientHeight - obj.offsetHeight) { T = document.documentElement.clientHeight - obj.offsetHeight; } obj.style.left = L + 'px'; obj.style.top = T + 'px'; }
五、碰撞
拖动一个元素去碰撞一个元素。
根据九宫格原理来实现。
document.onmousemove = function(ev) { var ev = ev || event; var L = ev.clientX - disX; var T = ev.clientY - disY; var L1 = L; var R1 = L + obj.offsetWidth; var T1 = T; var B1 = T + obj.offsetHeight; var L2 = oImg.offsetLeft; var R2 = L2 + oImg.offsetWidth; var T2 = oImg.offsetTop; var B2 = T2 + oImg.offsetHeight; if ( R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2 ) { oImg.src = '1.jpg'; } else { oImg.src = '2.jpg'; } obj.style.left = L + 'px'; obj.style.top = T + 'px'; }
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。