vue自定义v-drag指令实现鼠标拖拽

vue自定义v-drag指令实现鼠标拖拽

1. 效果

使用自定义拖拽指令v-drag来实现鼠标拖拽的效果。
在这里插入图片描述

2. 相关概念

  • Element.clientWidth:元素可视宽度(不包含滚动条)。
  • Element.clientHeight:元素可视高度(不包含滚动条)。
  • MouseEvent.clientX:鼠标相对于浏览器左上顶点的水平坐标(不包含滚动条),与之对应的MouseEvent.pageX:相对于整个文档的水平坐标(即包含滚动)。
  • MouseEvent.clientY:鼠标相对于浏览器左上顶点的垂直坐标(不包含滚动条),与之对应的MouseEvent.pageY:相对于整个文档的垂直坐标(即包含滚动)。
  • HTMLElement.offsetLeft:当前元素左上角相对于父节点(HTMLElement.offsetParent)的左边偏移的距离。
  • HTMLElement.offsetTop:当前元素左上角相对于父节点(HTMLElement.offsetParent)的顶部偏移的距离。
    在这里插入图片描述

3. 实现思路

自定义拖拽指令v-drag,实现思路如下:

  • 给需要拖拽的元素设置 position: fixed或者position:absolute定位,使得当前元素的位置是相对于浏览器左上顶点的位置。

注意区分Position的几个属性值:

  • Absolute:绝对定位,是相对于最近的且不是static定位的父元素来定位。
  • Fixed:绝对定位,是相对于浏览器窗口来定位的,是固定的,不会跟屏幕一起滚动。
  • Relative:相对定位,是相对于其原本的位置来定位的。
  • Relative:相对定位,是相对于其原本的位置来定位的。

元素的位置是通过调整左上顶点坐标来的,所以我们要知道元素拖拽后的左上顶点坐标,这样才能将元素移动到指定位置。

首先要计算出鼠标在移动元素前在元素上的位置 :

let disX = e.clientX - el.offsetLeft;
let disY = e.clientY - el.offsetTop;

知道了鼠标的相对位置,后续的鼠标移动,只要知道移动后的鼠标坐标,就能很容易的把当前位置元素的左上顶点坐标算出来。

计算元素移动后的左上顶点坐标:

el.style.left = e.clientX - disX + "px"; //设置定位元素的左部位置
el.style.top = e.clientY - disY + "px"; //设置定位元素的顶部位置

总体流程:鼠标按下时获取获取鼠标在元素上的位置,每次移动时不断计算和设置元素左上顶点坐标位置,并且在鼠标松开时要禁用掉down的监听事件,否则会一直执行。

4. 代码

在组件中使用directives注册一个自定义拖拽指令v-drag,在想要拖动的元素上使用“v-drag”即可。

扫描二维码关注公众号,回复: 15620199 查看本文章
  • 实现代码
<template>
  <div class="box" v-drag></div>
</template>

<script>
export default {
    
    
  //注册局部自定义指令
  directives: {
    
    
    //el:指令所绑定的元素
    drag(el, bindings) {
    
    
      //鼠标按下事件
      el.onmousedown = function(e) {
    
    
      	// 获取鼠标在元素上的位置
        let disX = e.clientX - el.offsetLeft;
        let disY = e.clientY - el.offsetTop;
        //鼠标移动事件
        document.onmousemove = function(e) {
    
    
          el.style.left = e.clientX - disX + "px"; //设置定位元素的左部位置
          el.style.top = e.clientY - disY + "px"; //设置定位元素的顶部位置
        };
        //鼠标松开事件
        document.onmouseup = function() {
    
    
          //要禁用掉down的监听事件,否则会一直执行
          document.onmousemove = document.onmouseup = null;
        };
      };
    },
  },
};
</script>

<style scoped>
.box {
    
    
  width: 300px;
  height: 300px;
  background-color: cyan;
  position: fixed;
  left: 100px;
  top: 100px;
}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_43288600/article/details/121431120