原生js拖拽事件

411 阅读2分钟

概述

拖拽这个功能,一般用的不多,不过,可以用来做一些有意思的东西,一般业务里面,常见的是拖拽上传文件,这里记录一下拖拽的实现,以及一些注意事项。

效果

动画.gif

事件

拖拽事件分为了三个

  • mousedown:绑定到需要进行拖拽的元素上
  • mousemove:绑定到需要脱拽的document上
  • mouseup:绑定到document上,一般拖拽鼠标抬起的时候,清除绑定的move和up事件,避免出现事件在鼠标都抬起了,事件还在触发。

实现原理

首先需要知道鼠标事件对象和dom元素的几个属性:

  • e.clientX :鼠标点到页面最左侧的距离
  • e.clientY :鼠标点到页面最顶部的距离
  • dom.offsetLeft:dom元素距离定位父级左侧的距离,没有定位父级为默认为页面边缘
  • dom.offsetTop:dom元素距离定位父级顶部的距离,没有定位父级为默认为页面边缘

image.png

image.png

当我们在拖拽过程中,鼠标点距离元素最左侧和最上面的距离是不变的,因此我们可以在dom元素被按下的时候求出来,如下图,按下拖拽过程中,这段距离是不变的,我们可以求出来。

    //方法1:
        let offsetLeft = e.clientX - test.offsetLeft;//水平鼠标点距离dom元素左边的距离
        let offsetTop = e.clientY - test.offsetTop;//垂直鼠标点距离dom元素左边的距离
    //方法2:offsetX可以直接获取鼠标点到元素最左边和最上面的距离,但是这个属性是实验性的,不推荐
         let offsetLeft = e.offsetX;
        let offsetTop = e.offsetX;
        

image.png 因此拖拽过程中,我们只需要计算对应定位的left和top距离就可以了,距离计算看下图: 鼠标移动过程中,只需要那e.clientX减去上面计算出来的offsetLeft就行啦

           dom.style.left = e.clientX - offsetLeft + 'px';
          dom.style.top = e.clientY - offsetTop + 'px';

image.png 这样我们就可以拖拽生效了,但是当我们鼠标离开后,应该清除鼠标移动事件和抬起事件,避免鼠标离开了,但是鼠标拖拽还在生效。

代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <style>
      * {
        margin: 0;
        padding: 0;
      }
      .test {
        width: 100px;
        height: 100px;
        background-color: #008c8c;
        /* 拖动元素记得定位 */
        position: relative;
        left: 0;
        top: 0;
      }
    </style>
  </head>
  <body>
    <div class="test"></div>
    <script>
      let test = document.querySelector('.test');
        // dom元素按下事件
      test.addEventListener('mousedown', e => {
        // 记录鼠标点到元素左边和顶部的距离
        let offsetLeft = e.clientX - test.offsetLeft;
        let offsetTop = e.clientY - test.offsetTop;
        // 拖动事件
        function moveMove(e) {
            // 计算left和top的位移
          test.style.left = e.clientX - offsetLeft + 'px';
          test.style.top = e.clientY - offsetTop + 'px';
        }
        // 抬起事件
        function mouseup(e) {
            // 移除事件
          document.removeEventListener('mousemove', moveMove);
          document.removeEventListener('mouseup', mouseup);
        }
        // 添加拖动和抬起事件
        document.addEventListener('mousemove', moveMove);
        document.addEventListener('mouseup', mouseup);
        // 移除默认事件和冒泡
        return false;
      });
    </script>
  </body>
</html>