注意点
- 在弹窗外加一层div,指令加在div上,不要直接加在弹窗上,会报错
- 在指令上给弹窗加一个高度,用
vh
单位,加高度是为了计算后续的移动边界 - 全屏状态下不允许移动
<div v-drag="'40vh'">
<el-dialog ref="dialogRef" v-model="open" title="Tips" :close-on-click-modal="false">
....
</el-dialog>
</div>
效果
代码
/加载需要的样式
require("./drag.scss");
let value = (el, binding) => {
console.log("绑定的值:", binding);
//弹窗
let dialog = document.getElementsByClassName("el-dialog")[0];
console.log("弹窗", dialog);
//初始化不最大化
el.fullscreen = false;
//获取弹窗的初始宽高,这里不设置默认高度,设置默认高度会影响页面的样式
let defaultWidth = dialog.style.width;
let defaultHeight = (dialog.style.height = binding.value || "50vh");
console.log("默认宽高:", defaultWidth, defaultWidth);
//设置弹窗初始边距,以弹窗左上角为起始点,后面的边界计算以此为基础
dialog.style.left = "0px";
dialog.style.top = "0px";
//获取弹窗头,加上放大,缩小图标
let dialogHeader = document.getElementsByClassName("el-dialog__header")[0];
//修改鼠标移入表头的样式
dialogHeader.classList.add("move_dialog");
//修改弹窗表头样式
dialogHeader.classList.add("dialog_header");
//防止标题被选中
dialogHeader.onselectstart = () => false;
//通过输出表头,可以看出关闭按钮是一个button
console.log("表头", dialogHeader);
let maxOrMinList = document.getElementsByClassName("max_or_min");
//防止重复添加
let maxOrMin = document.createElement("button");
//放大、缩小按
maxOrMin.className += "el-dialog__headerbtn max_or_min";
maxOrMin.innerHTML = `<i class="el-icon-full-screen"/></i>`;
//给按钮添加事件,实现放大和缩小
maxOrMin.onclick = () => {
if (el.fullscreen) {
//缩小
dialog.style.marginTop = "15vh";
dialog.style.width = defaultWidth;
// dialog.style.height = "auto";
maxOrMin.innerHTML = `<i class="el-icon-full-screen"/></i>`;
} else {
//放大
dialog.style.marginTop = "10vh";
dialog.style.width = "90%";
dialog.style.top = "0px";
maxOrMin.innerHTML = `<i class="el-icon-copy-document"/></i>`;
}
el.fullscreen = !el.fullscreen;
};
if (maxOrMinList.length == 0) {
//将按钮插入弹窗头部
dialogHeader.appendChild(maxOrMin);
}
//鼠标拖动,给表头添加事件
//鼠标拖拽,必须是在鼠标按下之后,松开之前进行
dialogHeader.onmousedown = (ev) => {
//全屏时不允许拖拽
if (el.fullscreen) {
return false;
}
//获取点击时鼠标的坐标
let dx = ev.clientX || ev.pageX;
let dy = ev.clientY || ev.pageY;
//定义一个开关,默认鼠标点击之后开启
let flag = true;
//绑定鼠标移动事件,要在全屏移动,所以用绑定document
document.onmousemove = (e) => {
if (flag) {
/** **********************横向移动********************** */
//横向移动距离
let moveLeft = parseInt(dialog.style.left);
//屏幕宽高
let windowWidth = document.documentElement.clientWidth;
//计算横向移动范围,屏幕宽度*(100% - 弹窗宽度)*0.5
let rangeLeft =
windowWidth * (100 - parseInt(dialog.style.width)) * -0.005;
let rangeRight =
windowWidth * (100 - parseInt(dialog.style.width)) * 0.005;
console.log("横向范围:", rangeLeft, rangeRight);
console.log("横向:", e.movementX);
if (moveLeft > rangeLeft && moveLeft <= rangeRight) {
dialog.style.left = moveLeft + e.movementX + "px";
} else if (moveLeft <= rangeLeft) {
dialog.style.left = rangeLeft + 1 + "px";
} else if (moveLeft >= rangeRight) {
dialog.style.left = rangeRight - 1 + "px";
}
/** *****************************纵向移动************************** */
//纵向移动距离
let moveTop = parseInt(dialog.style.top);
//屏幕宽高
let windowHeight = document.documentElement.clientHeight;
//计算纵向移动距离,乘以0.15是因为,弹窗默认距离顶部的距离是15%
let rangeTop = windowHeight * -0.15;
//向下距离是屏幕高度-弹窗距离顶部高度-弹窗高度
let rangeBottom =
windowHeight * (100 - 15 - parseInt(dialog.style.height)) * 0.01;
console.log("纵向范围:", rangeBottom, rangeTop);
console.log("纵向:", e.movementY, moveTop); //往上是负值
if (moveTop < rangeBottom && moveTop > rangeTop) {
dialog.style.top = moveTop + e.movementY + "px";
} else if (moveTop >= rangeBottom) {
dialog.style.top = rangeBottom - 1 + "px";
} else if (moveTop <= rangeTop) {
dialog.style.top = rangeTop + 1 + "px";
}
console.log(dialog.style.top, rangeTop);
}
};
document.onmouseup = () => {
flag = false;
};
};
};
export default {
name: "drag",
mounted: value,
updated: value,
};
// 放大缩小按钮样式
.max_or_min {
color: #909399;
margin-right: 30px;
font-size: 15px;
}
// 平移样式,鼠标悬浮到弹窗头部,改变鼠标样式
.move_dialog:hover {
cursor: move;
}
// 弹窗表头样式
.dialog_header {
background-color: #e9e9e9;
}