JavaScript拖拽2——多元素、分离JS
上一节我们实现了基本的拖拽,但是需要给可拖拽的元素设置一个特定的id,然后再在JS中修改代码,使用起来比较麻烦。这样一旦文档结构发生变化就要调整JS代码,没有做到JavaScript与HTML分离的原则。
所以应该实现一个可以适用于多个元素的拖拽代码,而且代码在可拖拽元素改变后应该不需要修改而仍然能正常工作。
使用class做“钩子”
为了使代码适用于多个元素,我们使用它的class来指定元素是否可以拖拽。我们使用如下的JavaScript代码来遍历文档中所有的节点,然后让class为drag的元素可以被拖拽。
function dragInit(node){ if(node.className == "drag"){ node.onmousedown = down; node.onmousemove = move; node.style.position = "relative"; node.style.top = "0px"; node.style.left = "0px"; } var children = node.childNodes; for(var i = 0;i < children.length; i++){ dragInit(children[i]); } }
dragInit函数会逐个检查各个节点的class是否为drag,如是是,那么会为该元素设置鼠标经过、鼠标按下事件的响应函数。
多个元素一起移动的问题
上面我们已经实现了多个元素可移动的问题。可以进入这个网页测试一下。可以发现这个拖拽效果有一个严重的问题。当我们拖动div1的时候,如果鼠标路径经过了div2,那么两个div会同时移动。原因是这触发了div2的onmouseover事件。我们可以通过给元素设置z-index的方法来解决。因为当我们拖动z-index较高的元素经过z-index较低的元素时并不会触发z-index较低元素的鼠标经过事件。所以我们对代码做出如下修改:
<script type="text/javascript"> var max = 1;//定义一个max变量 ……其它部分不变 function down(event) { …… //保证点击元素的z-index最高 this.style.zIndex = max++; } </script>
我们设置了一个max变量来记录当前的z-index值,当点击一个元素的时候就用max的值来设置它的z-index属性,同时max的值会变大。这样就实现了每次拖拽一个元素的时候,不会触发其它元素的mouseover事件。但是,
我们发现,当拖动元素的速度非常快的时候,仍然会造成两个元素一起移动。我个人认为这是浏览器处理事件的延迟造成的。通过给每个对象分别设置一个判断拖拽状态的布尔变量dragging就可以解决这个问题了。最终的代码如下:
拖拽JavaScript代码
<script type="text/javascript"> var dragging = false; var mouseY; var mouseX; var max = 1; function dragInit(node){ if(node.className == "drag"){ node.onmousedown = down; node.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]); } } window.onload = function(){ dragInit(document); document.onmouseup = docUp; } function down(event) { event = event || window.event; dragging = true; this.dragging = true; mouseX = parseInt(event.clientX); mouseY = parseInt(event.clientY); objY = parseInt(this.style.top); objX = parseInt(this.style.left); this.style.zIndex = max++; } function move(event){ event = event || window.event; if(this.dragging == true && dragging == true){ var x,y; y = event.clientY - mouseY + objY; x = event.clientX - mouseX + objX; this.style.top = y + "px"; this.style.left = x + "px"; } } function up(){ this.dragging = false; } function docUp(){ dragging = false; } function over(){ this.style.cursor = "move"; } </script>
演示: