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”即可。
实现代码
<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>