前言

大家好,我是南木元元,热衷分享有趣实用的文章。本文来分享一下如何在vue中通过自定义指令的方式来实现鼠标拖拽的效果。

实现效果

实现效果就是鼠标按下蓝色区域的图形后,就能够进行元素的拖拽。
在这里插入图片描述

浏览器坐标属性

在介绍自定义指令之前,首先需要知道浏览器中常用的一些坐标属性。

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

实现思路

接下来就可以自定义拖拽指令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的监听事件,否则会一直执行。

实现代码

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

<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>

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~

Logo

前往低代码交流专区

更多推荐