如题,需要鼠标拖拽元素,而且不超出一个限定范围(外层dom)
先写个方法获取元素的边界绝对位置数值
/**
* 获取元素宽度高度绝对位置
* @param dom
* @returns
*/
export function getAbsBounds(dom: HTMLElement | Element) {
// 返回元素的大小及其相对于视口的位置
const tempObj = dom.getBoundingClientRect();
return {
top: tempObj.top,
bottom: document.body.getBoundingClientRect().height - tempObj.bottom,
left: tempObj.left,
right: document.body.getBoundingClientRect().width - tempObj.right,
width: tempObj.width,
height: tempObj.height,
};
}
组件mounted时获取外层dom的范围
private mounted() {
const ele = document.getElementById('yourDomId');
if (ele) {
this.mapBounds = getAbsBounds(ele);
}
}
created时注册指令
private created() {
Vue.directive('divDrag', dragFun);
}
dragFun的内容
/**
* 图例拖拽移动的指令内容
* @requires common:getAbsBounds
* @param dragBox 待拖动的节点
* @param binding 绑定的数据
*/
public static dragFun(dragBox: HTMLElement, binding: any) {
dragBox.onmousedown = (e_down: any) => {
// 算出鼠标相对元素的位置
const disX = e_down.clientX - dragBox.offsetLeft;
const disY = e_down.clientY - dragBox.offsetTop;
document.onmousemove = (e: any) => {
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
const left = e.clientX - disX;
const top = e.clientY - disY;
const right = document.body.getBoundingClientRect().width - (left + dragBox.offsetWidth);
const bottom = document.body.getBoundingClientRect().height - (top + dragBox.offsetHeight);
// 若当前元素将要超出限定范围 return
if (
left <= binding.value.mapBounds.left ||
top <= binding.value.mapBounds.top ||
right <= binding.value.mapBounds.right ||
bottom <= binding.value.mapBounds.bottom
) {
return;
}
// 移动当前元素
dragBox.style.left = left + 'px';
dragBox.style.top = top + 'px';
};
document.onmouseup = () => {
// 鼠标弹起来的时候不再移动
document.onmousemove = null;
// 预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
document.onmouseup = null;
// 刷新当前元素的位置
binding.bounds = getAbsBounds(dragBox);
};
};
}
指令绑定到目标dom上
<!-- 这里的bounds是当前元素的位置,mapBounds是外层限制区域的范围,
格式参考getAbsBounds方法的输出对象 -->
<div v-divDrag="{ bounds , mapBounds }" class="legend-item">
<template>your template</template>
</div>