近期在阅读客户对系统提出的需求时,看到客户说 框能否拖动,因为经常会挡住gis层内容。
作为一名“只有客户开心了,我才能开心”的忠实信徒,于是二话不说给他实现。
1.定义动态绑定样式
首先需要在div中定义样式(需要注意样式应该动态绑定)
<div class="wrap draggable-content"
:style="{
left: position.x + 'px',
top: position.y + 'px', // 定义div起始位置,也就是相对于浏览器左上角原点的位置
position: 'absolute',
cursor: isDragging ? 'grabbing' : 'grab'//通过三元表达式实现对话框在不同状态下光标的样式
}"
@mousedown="startDrag" // 定义方法startDrag 当鼠标按下时执行 所以用mousedown
>
left和top定义了div初始时的位置,也就是x轴和轴
2.对变量定义
// 定义响应式状态
const isDragging = ref(false) // 是否正在拖动
const position = ref({ x: 0, y: 0 }) // 当前位置
const startPosition = ref({ x: 0, y: 0 }) // 开始拖动时的位置
定义了isDragging来判断当前处于什么状态 是移动状态 还是停止状态 给定初始值 FALSE
因为在div的left和top中使用到了 position.x 和 position.y 来确定初始位置,所以需要定义position
(注意:我这里用的是ref,复杂数据类型建议用reactive)
我这里给的初始值x和y都是0 ,我希望他在原点处,如果想让他在任意地方可以用
window.innerWidth - ' xxx' px
window.innerHeight - 'xxx' px 来给定初始值
最后需要定义开始拖动时的位置 startPosition
3.实现对话框自由拖拽
定义三个函数(
startDrag 开始拖动处理函数,
handleDrag 拖动中处理函数,
stopDrag 停止拖动的处理函数
)
通过全局事件监听来触发对应的操作。
startDrag
// 开始拖动的处理函数
const startDrag = (event) => {
isDragging.value = true // 设置拖动状态为 true
startPosition.value = {
x: event.clientX - position.value.x, // 记录鼠标点击位置与元素位置的差值
y: event.clientY - position.value.y
}
// 添加全局事件监听
document.addEventListener('mousemove', handleDrag)
document.addEventListener('mouseup', stopDrag)
}
handleDrag
// 拖动过程中的处理函数
const handleDrag = (event) => {
if (!isDragging.value) return // 如果不是拖动状态则返回
position.value = {
x: event.clientX - startPosition.value.x, // 计算新位置
y: event.clientY - startPosition.value.y
}
}
stopDrag
当停止拖动时需要移除所有的事件监听
// 停止拖动的处理函数
const stopDrag = () => {
isDragging.value = false // 设置拖动状态为 false
// 移除事件监听
document.removeEventListener('mousemove', handleDrag)
document.removeEventListener('mouseup', stopDrag)
}
需要注意的是:当我刚开始拖动时,需要给startPosition 赋值,记录鼠标位置和元素位置的差值
在拖动的过程中:就需要给position赋值 通过鼠标位置和元素位置的插值来实现div的拖动效果。
完整代码如下:
<template>
<!-- 主容器 div -->
<div
:style="{ <!-- 动态样式绑定 -->
left: position.x + 'px', <!-- X轴位置 -->
top: position.y + 'px', <!-- Y轴位置 -->
position: 'absolute', <!-- 绝对定位 -->
cursor: isDragging ? 'grabbing' : 'grab' <!-- 根据拖动状态改变鼠标样式 -->
}"
@mousedown="startDrag" <!-- 鼠标按下时触发拖动 -->
>
<!-- 表格内容 -->
<el-table ... />
</div>
</template>
// 导入所需的 Vue 组合式 API
import { ref, onMounted, onUnmounted } from 'vue'
// 定义响应式状态
const isDragging = ref(false) // 是否正在拖动
const position = ref({ x: 0, y: 0 }) // 当前位置
const dragRef = ref(null) // DOM 引用
const startPosition = ref({ x: 0, y: 0 }) // 开始拖动时的位置
// 开始拖动的处理函数
const startDrag = (event) => {
isDragging.value = true // 设置拖动状态为 true
startPosition.value = {
x: event.clientX - position.value.x, // 记录鼠标点击位置与元素位置的差值
y: event.clientY - position.value.y
}
// 添加全局事件监听
document.addEventListener('mousemove', handleDrag)
document.addEventListener('mouseup', stopDrag)
}
// 拖动过程中的处理函数
const handleDrag = (event) => {
if (!isDragging.value) return // 如果不是拖动状态则返回
position.value = {
x: event.clientX - startPosition.value.x, // 计算新位置
y: event.clientY - startPosition.value.y
}
}
// 停止拖动的处理函数
const stopDrag = () => {
isDragging.value = false // 设置拖动状态为 false
// 移除事件监听
document.removeEventListener('mousemove', handleDrag)
document.removeEventListener('mouseup', stopDrag)
}
// 组件卸载时的清理函数
onUnmounted(() => {
// 移除所有事件监听
document.removeEventListener('mousemove', handleDrag)
document.removeEventListener('mouseup', stopDrag)
})