鼠标事件实现拖拽

4,030 阅读3分钟

为什么需要拖拽

当前的互联网用户早已习惯了拖拽,习惯了拖拽带来的便利。任何一个前端项目都有加入拖拽这个功能的可能性。

拖拽的实现方案

  1. 鼠标事件实现
  2. 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.

仔细把玩上面的示例问题就会出现在我们面前:当移动鼠标过快,小球会脱离拖拽

fisrt.gif

如何解决小球突然的停顿

为了解决小球的突然停顿,我们需要了解让小球突然停顿的原因。 上一版实现的代码中mousemove事件绑定到了元素本身,这意味着当鼠标移出元素所 占据的范围的时候,元素会停止移动。这就是小球突然停顿的原因。

为了解决这个问题,我们需要将mousemove事件绑定到 document 上。下面是改动后的示例 ,这次快速移动鼠标,小球再也不会停顿。

See the Pen 拖拽实现2 by 柏 (@Ai01) on CodePen.

second.gif

如何实现对拖拽元素的放置

当元素被拖拽到目标位置时,放开鼠标右键,被拖拽元素需要被放入目标元素内部。 要想实现这个功能,需要利用到document.elementFromPointapi。这个 api 可以将 当前位置的顶部元素(z-index 最大)找到。下面是一个简单的示例

ball.hide = true;
const elementBelow = document.elementFromPoint(e.clientX, e.clientY);
ball.hide = false;

当发现elementBelow与目标元素相同时,可以完成剩余的逻辑:

third.gif

See the Pen 拖拽放置 by 柏 (@Ai01) on CodePen.

上面就是一个完整的拖拽与放置示例。

思考

读者看到这里应该已经通读了整篇文章,可以在脑海中回想一下整个过程,确认自己是否理解。如果已经理解,可以问一下自己下面这个问题:

  • 当有多个元素需要实现拖拽的时候,如何将拖拽功能抽取出来进行统一?

最后

希望看到文章的同学,可以有收获。如果文章中,有什么错误请指出。