javascript拖拽的简单实现
以前没写过的时候一直都觉得在页面中实现一个元素的鼠标拖拽功能是一件很难的事情,但是当你动手开始写的时候你会发现其实这个并没有想象中的那么难。当然有的人动手写起来的时候还是有点吃力的,我在这里简单讲解一下使用javascript在页面中做出元素的鼠标拖拽功能的简单实现。当然比我写的好的有很多,这里不会实现太多的例子,只是讲一个最简单的实现原理,再实现一个简单的实例,引导新手也步入js拖拽的世界,主要还要靠自己动手去实现。
简单来说,鼠标对元素的拖拽的过程也就是:
1、对要实现拖拽功能的元素(下称目标元素)块按下鼠标左键且不放手;
2、移动鼠标;
3、松开鼠标左键,一次拖拽完成
那么用js实现鼠标对元素的拖拽的思想就是:
1、对目标元素注册mousedown事件,记录下处于mousedown状态时的目标元素的位置和鼠标的位置;
2、在mousedown事件的处理函数中对document注册mousemove事件,在mousemove的处理函数中随鼠标位置变化修改被拖元素的位置;
3、在mousedown事件的处理函数中对document注册mouseup事件,在mouseup的处理函数中将注册的mousemove事件清除;
对实现思想的解释:
1、这点好理解,既然要有拖拽功能,就需要有鼠标按下状态、按着鼠标移动元素的状态和松开鼠标的状态,并且前提是鼠标在目标元素区域左键被按下,否则移动鼠标也是无效的。另外,要实现跟随鼠标位置移动也就需要记录下mousedown状态时的目标元素的位置和鼠标位置,因为之后的移动的位置计算需要用到最初mousedown状态的位置;
2、(1)对document注册mousemove事件是因为你可能鼠标拖动的情况下,被拖元素可能到了某个位置就被限制不能动了,但是鼠标是不能收控制的,会移出目标元素占用的区域,那把事件绑在document中就避免了鼠标移出目标元素占用区域时拖动失效的问题;(2)因为任何一个鼠标事件发生时都会产生一个事件对象,这个对象中会包含鼠标事件发生时所处位置的信息:clientX属性为X方向距离浏览器左上角的大小、clientY属性为Y方向距离浏览器左上角的大小,单位为px,所以就可以根据mousemove时鼠标的位置和mousedown时记录下的位置计算得移动时目标元素的新位置。当然,这里在拖动的过程中也可以对目标元素的X方向或者Y方向的位置进行限制,限制其不能超过某个值;(3)这里强烈建议把目标元素的position属性设置为"absolute"或者"fixed"值,这是为什么呢?因为第一position为absolute或fixed你对鼠标移动时的元素位置计算会更简单,因为目标元素脱离文档流了你移动他时他的布局不受其他元素的影响,其他元素的布局也不受目标元素的影响;第二出于对性能的考虑,既然目标元素布局与其他元素的布局互不影响那在mousemove时就不会发生那么多重排,发生mousemove事件时是连续不间断的,如果在这时候要不断地进行重排的话会进行非常密集的计算,耗费很多浏览器的资源;
3、当鼠标左键松开时注册一个mouseup事件,这时候因为鼠标松开了所以这一次拖拽就算完成了,这时候一定要将之前注册的mousemove事件清除掉,否则当你鼠标左键松开手了,移动鼠标目标元素还会被你移动。
一个拖拽过程就这这么实现了...
理解了三点思想实现起来就不难了!
下面是一个用js制作的元素拖拽的简单例子:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>drag</title> </head> <body> <div id="ele" style="width:100px;height:100px;background:#ccc;cursor:move;position:absolute;top:0;left:0;"></div> </body> <script> function addEvent(ele, eventType, handler){ if(ele.addEventListener){ ele.addEventListener(eventType, handler, false); } else if(ele.attachEvent){ ele.attachEvent("on" + eventType,handler); } } function removeEvent(ele, eventType, handler){ if(ele.removeEventListener){ ele.removeEventListener(eventType, handler, false); } else if(ele.detachEvent){ ele.detachEvent("on" + eventType,handler); } } var ele = document.getElementById('ele'); ele.onmousedown = function (e) { e = e || window.event; var elementX = parseInt(ele.style.left, 10); //记录mousedown状态目标元素的X方向位置 var elementY = parseInt(ele.style.top, 10); //记录mousedown状态目标元素的Y方向位置 var clientX = e.clientX; //记录mousedown状态鼠标的X方向位置 var clientY = e.clientY; //记录mousedown状态鼠标的Y方向位置 var mousemoveHandler = function (e) { e = e || window.event; var moveX = e.clientX - clientX; //这几行涉及到mousemove时的位置计算 var moveY = e.clientY - clientY; var newElementX = elementX + moveX; var newElementY = elementY + moveY; // if (newElementX > 900) { //可做出移动范围限制 // newElementX = 900; // } ele.style.left = newElementX + 'px'; ele.style.top = newElementY + 'px'; }; var mouseupHandler = function () { removeEvent(document, 'mousemove', mousemoveHandler); //在mouseup处理函数中清除掉mousemove事件 }; addEvent(document, 'mousemove', mousemoveHandler); //在mousedown处理函数中添加mousemove事件 addEvent(document, 'mouseup', mouseupHandler); //在mousedown处理函数中添加mouseup事件 }; </script> </html>