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';
}
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。