原文来自:[url]http://www.cainiao8.com/web/js_examples/15_tuozhuai3.html[/url]
上一节我们让拖拽代码使用起来更方便、适用于多个元素,同时解决了偶尔会出现的拖动一个元素,多个元素一起移动的问题。但是在快速拖拽的时候,会出现延迟,或者元素干脆就停止移动了。
元素停止移动的原因
分析一下上面问题的原因:鼠标滑动地太快,自然会造成mousemove事件多次发生,相应的,事件处理函数也多次被调用,自然造成延迟。延迟之后,元素移动的速度赶不上鼠标移动的速度,可能造成鼠标移出元素的状态,从而触发了mouseout事件,从而造成了被拖动元素停止移动。
为了验证上面的想法,我们给元素添加一个onmouseout的响应函数,来显示一段字符串。修改代码如下:
点击进入[url=http://www.cainiao8.com/web/js_examples/tuozhuai_ex3_fail.html]测试页面[/url],可以发现浏览器对mouseout十分敏感,我在IE和FF下做了测试,只要稍微移动的快一点,就会触发鼠标移出事件。但是只要在视觉上鼠标还没有移出元素,那么元素还是可以正常移动的。但是如果鼠标“看起来”移出了元素,那么拖拽效果就真的彻底被破坏了。
解决快速拖拽时元素停止移动的问题
这个问题是不可避免的吗?当然不是,如果你是豆瓣的用户,可以进入“我的豆瓣”栏目测试一下它们的拖拽功能()。就算拖拽的速度再快也不会出现“突然停止”的情况。
我们也来试着解决这个问题。上面已经分析了,造成元素停止移动的原因是鼠标移出了被拖拽的元素,造成mousemove事件无法得到响应。那么我们让 mousemove事件在有延迟的情况下仍然可以被响应就可以了,我们只要把事件处理函数加到document上就可以做到这一点了(之前也想过其它解决方案,但是失败了)。修改之后的代码如下:
可以在修改之后的[url=http://www.cainiao8.com/web/js_examples/tuozhuai_ex3.html]测试页面实验一下[/url],无论速度多快,延迟都不会造成被拖拽元素停止移动的问题。下面就解释一下主要的修改之处:
1. 使用全局变量dragElement来标记当前拖拽元素。
2. dragInit函数中,给document定义mouseover的响应函数。
3. mousemove的响应函数的针对对象不再是this,而是dragElement。
JavaScript拖拽系列
1. JavaScript拖拽
2. JavaScript拖拽2——多元素、分离JS
3. JavaScript拖拽3——解决快速拖拽的问题
4. JavaScript拖拽4——获得元素的位置
5. JavaScript拖拽5——性能优化
6. JavaScript拖拽6——修复错误
上一节我们让拖拽代码使用起来更方便、适用于多个元素,同时解决了偶尔会出现的拖动一个元素,多个元素一起移动的问题。但是在快速拖拽的时候,会出现延迟,或者元素干脆就停止移动了。
元素停止移动的原因
分析一下上面问题的原因:鼠标滑动地太快,自然会造成mousemove事件多次发生,相应的,事件处理函数也多次被调用,自然造成延迟。延迟之后,元素移动的速度赶不上鼠标移动的速度,可能造成鼠标移出元素的状态,从而触发了mouseout事件,从而造成了被拖动元素停止移动。
为了验证上面的想法,我们给元素添加一个onmouseout的响应函数,来显示一段字符串。修改代码如下:
<script type="text/javascript">
function dragInit(node){
if(node.className == "drag"){
……
node.onmouseout = out;
……
}
……
}
……
function out(){
alert("鼠标一出去啦,我不能再移动啦!!");
}
……
</script>
点击进入[url=http://www.cainiao8.com/web/js_examples/tuozhuai_ex3_fail.html]测试页面[/url],可以发现浏览器对mouseout十分敏感,我在IE和FF下做了测试,只要稍微移动的快一点,就会触发鼠标移出事件。但是只要在视觉上鼠标还没有移出元素,那么元素还是可以正常移动的。但是如果鼠标“看起来”移出了元素,那么拖拽效果就真的彻底被破坏了。
解决快速拖拽时元素停止移动的问题
这个问题是不可避免的吗?当然不是,如果你是豆瓣的用户,可以进入“我的豆瓣”栏目测试一下它们的拖拽功能()。就算拖拽的速度再快也不会出现“突然停止”的情况。
我们也来试着解决这个问题。上面已经分析了,造成元素停止移动的原因是鼠标移出了被拖拽的元素,造成mousemove事件无法得到响应。那么我们让 mousemove事件在有延迟的情况下仍然可以被响应就可以了,我们只要把事件处理函数加到document上就可以做到这一点了(之前也想过其它解决方案,但是失败了)。修改之后的代码如下:
<script type="text/javascript">
//使用该变量标识拖拽的元素
var dragElement = null;
……
function dragInit(node){
if(node.className == "drag"){
node.onmousedown = down;
//使用document响应mousemove事件
document.onmousemove = move;
node.onmouseover = over;
//删除该函数node.onmouseup = up;
node.style.position = "relative";
node.style.top = "0px";
node.style.left = "0px";
node.dragging = false;
}
var children = node.childNodes;
for(var i = 0;i < children.length; i++){
dragInit(children[i]);
}
}
function down(event)
{
……
}
function move(event){
event = event || window.event;
//判断dragElement是否为null,即是否为拖拽状态
if(dragElement){
var x,y;
y = event.clientY - mouseY + objY;
x = event.clientX - mouseX + objX;
//改变dragElement的位置
dragElement.style.top = y + "px";
dragElement.style.left = x + "px";
}
}
function docUp(){
//停止拖拽
dragElement = null;
}
……
</script>
可以在修改之后的[url=http://www.cainiao8.com/web/js_examples/tuozhuai_ex3.html]测试页面实验一下[/url],无论速度多快,延迟都不会造成被拖拽元素停止移动的问题。下面就解释一下主要的修改之处:
1. 使用全局变量dragElement来标记当前拖拽元素。
2. dragInit函数中,给document定义mouseover的响应函数。
3. mousemove的响应函数的针对对象不再是this,而是dragElement。
JavaScript拖拽系列
1. JavaScript拖拽
2. JavaScript拖拽2——多元素、分离JS
3. JavaScript拖拽3——解决快速拖拽的问题
4. JavaScript拖拽4——获得元素的位置
5. JavaScript拖拽5——性能优化
6. JavaScript拖拽6——修复错误