思路:
(1)首先通过拖拽物体,找到拖拽过程中进行变更的 dom 的属性值。
(2)获取到当前界面的总高度和总宽度。
(3)获取到需要进行拖拽的物体的高度和宽度,注意,拖拽物体的高度和宽度最好是具体数值而不是百分比,否则在处理四个角的时候会出现错误。
(4)获取物体拖拽是的运动坐标,上下(offsetTop)、左右(offsetLeft)。 注意,是拖拽物体的属性,不要找错对象
(5)通过测试得知 计算时以拖拽物体的 左边界 和 上边界 为准。
(6)判断物体移动到最右边:offsetLeft > (当前界面的总宽度 - 物体的宽度)。
(7)判断物体移动到最左边:offsetLeft 为 0 。
(8)判断物体移动到最下边:offsetTop > (当前界面的总高度 - 物体的高度) 。
(9)判断物体移动到最上边:offsetTop 为 0 。
(10)拖拽过程中各种属性的获取方法是通过监听鼠标移动事件实现的。
具体操作如下:
1、新建文件
<el-dialog
:visible.sync="dialogVisible"
:closeOnClickModal="false"
class="NewDialog"
v-dialog-drag
title="弹窗拖拽"
>
</el-dialog>
2、绑定鼠标(按下,松开)监听事件
// 进入界面时添加鼠标点击和松开的监听事件
mounted() {
window.addEventListener("mousedown", this.mouseDown);
window.addEventListener("mouseup", this.mouseUp);
},
3、编辑鼠标事件
// 鼠标监听事件
// 鼠标长按的时候添加 鼠标移动监听事件
mouseDown() {
window.addEventListener("mousemove", this.mouseMove);
},
//鼠标松开的时候删除鼠标移动监听事件
mouseUp() {
window.removeEventListener("mousemove", this.mouseMove);
},
// 鼠标移动判断当前弹窗位置,限制住弹窗移动区域
mouseMove() {
// RelaHeight : 界面总高度 - 物体高度(以上边界为准)
// RelaWidth : 界面总宽度 - 物体宽度(以左边界为准)
// MoveTop : 物体上下移动的坐标变化
// MoveLeft : 物体左右移动的坐标变化
// DomSty : 需要修改的dom
let RelaHeight =
document.getElementById("app").offsetHeight -
document.getElementsByClassName("el-dialog")[0].offsetHeight,
RelaWidth =
document.getElementById("app").offsetWidth -
document.getElementsByClassName("el-dialog")[0].offsetWidth,
MoveTop = document.getElementsByClassName("el-dialog")[0].offsetTop,
MoveLeft = document.getElementsByClassName("el-dialog")[0].offsetLeft,
DomSty = document.getElementsByClassName("el-dialog")[0].style;
this.$VerdictDrag(RelaHeight, RelaWidth, MoveLeft, MoveTop, DomSty);
},
4、新建 verdictDrag.js
src - > utils -> verdictDrag.js
if (ChangeSty.left) {
if (Left > relaWidth) {
ChangeSty.left = relaWidth + "px";
}
// 最左边
if (Left < 0) {
ChangeSty.left = 0;
}
// 最上边
if (Top < 0) {
ChangeSty.top = 0;
}
// 最下边
if (Top > relaHeight) {
ChangeSty.top = relaHeight + "px";
}
return ChangeSty;
}
5、导入到 utils -> index.js
在 src -> utils 中新建 index.js文件,将 verdictDrag.js
然后在main.js 中将 utils注册一下,这里可以看这篇文章 定义全局方法,然后就全局可以使用 VerdictDrag()。
6、移除鼠标监听事件
// 离开界面的时候删除鼠标监听事件
destroyed() {
window.removeEventListener("mousedown", this.mouseDown);
window.removeEventListener("mouseup", this.mouseUp);
},
7、注意事项
(1)在长按鼠标进行拖拽的时候会出现弹窗无移动,但是弹窗内容进行了位移同时鼠标指针样式变为 cursor: default 时的样式。这个时候松开鼠标mouseMove 方法未移除,需要重新点击之后才会移除。但是此问题目前只有在边界的时候才有几率出现,暂未解决。
(2)element 的弹窗组件貌似会自带 margin属性,为了计算方便,对此处样式进行了修改,如图:
首先是将弹窗自带的margin值调为0
这个时候弹窗会出现左上角,此处的操作是通过 flex 布局,将弹窗定位在页面中央:
这里对 margin 属性进行操作是因为如果不去掉,在计算数值的时候除了 界面总高/宽度、物体高/宽度外,还需要额外计算 margin 的值以及加上 margin 后导致的页面样式问题。为求计算方便,决定将 margin 设置为0。
ps:iview组件好像不需要这一步操作。
新手理解,若有误,请各位大佬指点,Thanks♪(・ω・)ノ