【vue】dom元素拖拽指令
commonDrag.js:
/**
* v-commonDrag 弹窗拖拽
* @params operate {String} 拖拽项的data-drag-name
* @params move
*/
export const commonDrag = {
inserted(el, binding) {
const { operate, move } = binding.value;
if (typeof binding.value !== 'object') {
throw new Error('参数错误!');
}
if (!move || operate === false || operate === '') return;
// 获取拖拽内容头部
const operateElList = el.querySelectorAll(`[data-drag-name="${operate}"]`);
// 获取拖拽容器
let dragDom;
if (move === true) {
dragDom = el;
} else {
dragDom = document.querySelector(`[class*="${move}"]`);
}
if (!dragDom || !operateElList?.length) return;
const containerRect = dragDom.parentNode.getBoundingClientRect();
let isDragging = false;
let isInit = false;
let oldX, oldY;
let oldTX, oldTY;
let minLeft, maxLeft, minTop, maxTop;
const gap = 20; // 与父容器间的间距
// 鼠标按下事件
function onMouseDown(e) {
isDragging = true;
if (!Array.from(operateElList).includes(e.target)) return;
e.stopPropagation();
oldX = e.clientX;
oldY = e.clientY;
const { transform } = dragDom.style;
const oldT = transform.match(/translateX\(([^)]+)px\) translateY\(([^)]+)px\)/);
oldTX = oldT?.[1] ? Number(oldT?.[1]) : 0;
oldTY = oldT?.[2] ? Number(oldT?.[2]) : 0;
if (!isInit) {
const rect = dragDom.getBoundingClientRect();
// 边界限制
minLeft = containerRect.left - rect.left + gap;
maxLeft = containerRect.right - rect.right - gap;
minTop = containerRect.top - rect.top + gap;
maxTop = containerRect.bottom - rect.bottom - gap;
isInit = true;
}
// 添加鼠标移动和释放事件
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
// 鼠标移动事件
function onMouseMove(e) {
if (!isDragging) return;
const deltL = e.clientX - oldX; // 移动距离
const deltT = e.clientY - oldY;
// 计算新的位置
let newLeft = oldTX + deltL;
let newTop = oldTY + deltT;
newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft));
newTop = Math.max(minTop, Math.min(newTop, maxTop));
dragDom.style.transform = `translateX(${newLeft}px) translateY(${newTop}px)`;
}
// 鼠标释放事件
function onMouseUp() {
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
// 绑定鼠标按下事件
dragDom.addEventListener('mousedown', onMouseDown);
// 存储事件处理器以便在 unbind 时使用
el._onMouseUp = onMouseUp;
el._onMouseMove = onMouseMove;
el._onMouseDown = onMouseDown;
},
unbind(el) {
// 解绑所有事件
el.removeEventListener('mousedown', el._onMouseDown);
document.removeEventListener('mousemove', el._onMouseMove);
document.removeEventListener('mouseup', el._onMouseUp);
},
};
使用:
<div v-commonDrag="{ operate: operateUUid, move: true,draggable:draggable}">
<div :data-drag-name="operateUUid" />
</div>
import {commonDrag} from '@/utils/commonDrag.js'; // 指令插件
export default {
directives: {
commonDrag
},
data(){
operateUUid:1234,// 操作区id
draggable:true// 是否可拖拽
},
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律