基于Vue 撸一个指令实现拖拽功能

2020-06-12 20:50:23易采站长站整理

document.onmouseup = null;
};
}
},
// 每次重新打开 dialog 时,要将其还原
update(el) {
const target = el.children[0];
target.style.left = '';
target.style.top = '';
},
// 最后卸载时,清除事件绑定
unbind(el) {
const header = el.children[0].children[0];
header.onmousedown = null;
},
};
export default vDrap;

这样就实现了 最简单 的拖拽了,这样就 ok 了吗? 当然不是,这样会有什么问题呢?就是如果用力过猛把整个弹框都拖到可视区域之外了,那就抠不出来了。

所以还得完善一下,判断四个方向的边界,如果超过边界值就不动了。边界值实际上就是在屏幕上能拖动的最大距离也就是 disX 和 disY 的最大值

上边界: target.offsetTop
offsetTop :这里可以表示目标元素( target )上边框距离页面顶部的距离
下边界: body.height – target.offsetTop – header.height
header.height :预留高度,表示往下可以拖到只留下可拖拽区域在外面
左边界: target.offsetLeft + target.width – 50
offsetLeft :这里可以表示目标元素左边框距离页面左边的距离
50 :表示预留的宽度,可以自己随便定只要大于 0 即可,表示往左再怎么拖也会留下 50px 的宽度在外面
右边界: body.width – target.offsetLeft – 50

这里 50 同上,表示往左再怎么拖也会留下 50px 的宽度在外面

这里计算边界值的方法有多种,大家可以去尝试自己的想法。然后我粗略的画了一个图,帮助理解,虽然感觉只有我自己看得懂。哈哈。。。

 

下面用代码实现边界判断就 ok了


// ...
// 以上代码省略
header.onmousedown = (e) => {
// ...
// 以上代码省略
// 分别计算四个方向的边界值
const minLeft = target.offsetLeft + parseInt(getAttr(target, 'width')) - 50;
const maxLeft = parseInt(getAttr(document.body, 'width')) - target.offsetLeft - 50;
const minTop = target.offsetTop;
const maxTop = parseInt(getAttr(document.body, 'height'))
- target.offsetTop - parseInt(getAttr(header, 'height'));
document.onmousemove = (event) => {
// 鼠标移动时计算每次移动的距离,并改变拖拽元素的定位
const disX = event.clientX - currentX;
const disY = event.clientY - currentY;
// 判断左、右边界
if (disX < 0 && disX <= -minLeft) {
target.style.left = `${left - minLeft)}px`;
} else if (disX > 0 && disX >= maxLeft) {
target.style.left = `${left + maxLeft}px`;