【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// 是否可拖拽
},
}

浙公网安备 33010602011771号