为什么需要拖拽
当前的互联网用户早已习惯了拖拽,习惯了拖拽带来的便利。任何一个前端项目都有加入拖拽这个功能的可能性。
拖拽的实现方案
- 鼠标事件实现
- drag and drop api
这两种实现方案各自有自己的场景。鼠标实现的好处在于有更好的兼容性,坏处就是更多的代码。 dragApi 实现的好处在于更少的代码,坏处就是更差的兼容性。
这篇文章来探讨的就是如何利用鼠标事件实现拖拽
基础原理
需要利用mousedown
, mousemove
, mouseup
三个事件来完成原生拖拽实现。
mousedown
是鼠标左键按下的事件mousemove
是鼠标移动事件mouseup
是鼠标左键放开的事件
整体的思路就是
- 在鼠标移动到当前元素的上方并且按下左键的事件开始,
- 当鼠标移动的时候,改变元素的位置。
- 当鼠标左键放开的时候,停止改变元素的位置。
其中改变元素位置是利用改变元素的 top 和 left 实现的。下面的代码是一个简单的示例。
let x = e.pageX - ball.offsetWidth / 2;
let y = e.pageY - ball.offsetHeight / 2;
ball.style.left = `${x}px`;
ball.style.top = `${y}px`;
如果你根据上面的思路来实现一个拖拽,会的到一个类似下面代码的示例:
See the Pen 拖拽实现 by 柏 (@Ai01) on CodePen.
仔细把玩上面的示例问题就会出现在我们面前:当移动鼠标过快,小球会脱离拖拽
如何解决小球突然的停顿
为了解决小球的突然停顿,我们需要了解让小球突然停顿的原因。
上一版实现的代码中将mousemove
事件绑定到了元素本身,这意味着当鼠标移出元素所
占据的范围的时候,元素会停止移动。这就是小球突然停顿的原因。
为了解决这个问题,我们需要将mousemove
事件绑定到 document 上。下面是改动后的示例
,这次快速移动鼠标,小球再也不会停顿。
See the Pen 拖拽实现2 by 柏 (@Ai01) on CodePen.
如何实现对拖拽元素的放置
当元素被拖拽到目标位置时,放开鼠标右键,被拖拽元素需要被放入目标元素内部。
要想实现这个功能,需要利用到document.elementFromPoint
api。这个 api 可以将
当前位置的顶部元素(z-index 最大)找到。下面是一个简单的示例
ball.hide = true;
const elementBelow = document.elementFromPoint(e.clientX, e.clientY);
ball.hide = false;
当发现elementBelow
与目标元素相同时,可以完成剩余的逻辑:
See the Pen 拖拽放置 by 柏 (@Ai01) on CodePen.
上面就是一个完整的拖拽与放置示例。
思考
读者看到这里应该已经通读了整篇文章,可以在脑海中回想一下整个过程,确认自己是否理解。如果已经理解,可以问一下自己下面这个问题:
- 当有多个元素需要实现拖拽的时候,如何将拖拽功能抽取出来进行统一?
最后
希望看到文章的同学,可以有收获。如果文章中,有什么错误请指出。