新建文件 directives.js
import Vue from 'vue';
// v-dialogDrag: 弹窗拖拽属性
Vue.directive('dialogDrag', {
bind(el, binding, vnode, oldVnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header');
const dragDom = el.querySelector('.el-dialog');
//dialogHeaderEl.style.cursor = 'move';
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = (function() {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr];
} else{
return (dom, attr) => getComputedStyle(dom, false)[attr];
}
})()
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
const screenWidth = document.body.clientWidth; // body当前宽度
const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
const dragDomheight = dragDom.offsetHeight; // 对话框高度
const minDragDomLeft = dragDom.offsetLeft;
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
const minDragDomTop = dragDom.offsetTop;
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
// 获取到的值带px 正则匹配替换
let styL = sty(dragDom, 'left');
let styT = sty(dragDom, 'top');
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if(styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
}else {
styL = +styL.replace(/\px/g, '');
styT = +styT.replace(/\px/g, '');
};
document.onmousemove = function (e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX;
let top = e.clientY - disY;
// 边界处理
if (-(left) > minDragDomLeft) {
left = -(minDragDomLeft);
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft;
}
if (-(top) > minDragDomTop) {
top = -(minDragDomTop);
} else if (top > maxDragDomTop) {
top = maxDragDomTop;
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
};
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
}
}
})
在main.js
中引入
import ‘./utils/directives’
在el-dialog标签中加入v-dialogDrag
属性
属性 close-on-click-modal 取消自动关闭
属性 modal:关闭遮罩
属性 class:注意class添加,overflow hidden否则有溢出
二开el-dialog可最大化,还原,拖动,调整大小
新建 @/components/max-dialog/index.vue
<!--
* @Author: Yorlg
* @Email: [email protected]
* @Date: 2023-01-03
* @Description: 二次封装el-dialog可最大化,还原,拖动,调整大小
-->
<template>
<el-dialog
ref="maxDialog"
custom-class="dialogHeightFull maxDialog"
:title="title"
:fullscreen="fullFlag"
:visible.sync="maxdialogVisible"
:modal="false"
:append-to-body="false"
:close-on-click-modal="false"
:show-close="false"
:width="width"
:top="top"
v-if="maxdialogVisible"
@closed="closeMaxDialog"
v-dialogDrag
>
<div slot="title" class="maxDialog-header">
<div class="maxDialog-title">
<span>{{ title }}</span>
</div>
<div class="maxDialog-icon">
<i
:class="fullFlag ? 'el-icon-copy-document' : 'el-icon-full-screen'"
@click="IsFullscreen"
></i>
<i class="el-icon-close" @click="closeMaxDialog"></i>
</div>
</div>
<slot name="content" :style="{ height: height }"></slot>
<div class="resize"></div>
</el-dialog>
</template>
<script>
export default {
name: 'maxDialog',
props: {
dialogVisible: {
type: Boolean,
default: false
},
width: {
type: String,
default: '1200px'
},
height: {
type: String,
default: '100%'
},
top: {
type: String,
default: '30px'
},
title: {
type: String,
default: ''
},
isfullscreen: {
type: Boolean,
default: false // 默认全屏
}
},
data () {
return {
full: false, // 全屏
}
},
computed: {
fullFlag: {
get: function () {
return this.full ?? this.isfullscreen;
},
set: function (n) {
return this.full
}
},
maxdialogVisible: { //重新设置一个变量,接收父级传递的参数
get: function () {
return this.dialogVisible
},
set: function (value) { }
}
},
mounted () {
},
methods: {
// 全屏 切换
IsFullscreen () {
let dialogDom = document.querySelector(".maxDialog");
if (this.isfullscreen == true) {
this.full = this.full === null ? false : !this.full
} else {
this.full = this.full === null ? true : !this.full
dialogDom.style.top = `0px`;
dialogDom.style.left = `auto`;
}
// 传过来的全屏钩子函数
this.$emit('maxFun')
},
// 关闭
closeMaxDialog () {
this.full = null
// 传过来的关闭钩子函数
this.$emit('closeDialog', 'childclose')
}
},
created () {
this.full = this.isfullscreen
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog__header {
background-color: #f2f2f2;
/* height: 48px; */
padding: 10px 20px 10px;
}
.maxDialog-header {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.maxDialog .maxDialog-icon i {
display: inline-block;
height: 28px;
width: 28px;
line-height: 24px;
text-align: center;
border-radius: 50%;
cursor: pointer;
font-size: 22px;
}
::v-deep .maxDialog.dialogHeightFull.el-dialog {
margin-bottom: 0;
overflow-y: hidden;
margin: none;
pointer-events: auto;
}
.el-dialog__wrapper {
overflow: hidden !important;
z-index: 0 !important;
pointer-events: none;
}
.maxDialog .maxDialog-icon i:hover {
background-color: #ddd;
}
.maxDialog .maxDialog-icon i::before {
font-size: 80%;
}
.resize {
position: absolute;
right: 0;
bottom: 0;
content: "";
width: 10px;
height: 10px;
cursor: se-resize;
}
</style>
新建 @/utils/directives.js
/**
* @Author: Yorlg
* @Email: [email protected]
* @Date: 2023-01-03
* @Description: 二次封装el-dialog可最大化,还原,拖动,调整大小
*/
import Vue from 'vue'
Vue.directive("dialogDrag", {
bind (el, binding, vnode, oldVnode) {
const windowW = document.body.clientWidth;
const windowH = document.body.clientHeight
//设置弹框可拉伸最小宽高
let minWidth = 400;
let minHeight = 300;
const dialogHeaderEl = el.querySelector(".el-dialog__header");
//弹窗
const dragDom = el.querySelector(".el-dialog");
//头部加上可拖动cursor
dialogHeaderEl.style.cursor = "move";
// 获取style属性
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
let moveDown = e => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
// 获取到的值带px 正则匹配替换
let styL, styT, styMT;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes("%")) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, "") / 100);
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, "") / 100);
} else {
styL = +sty.left.replace(/\px/g, "");
styT = +sty.top.replace(/\px/g, "");
styMT = +sty.marginTop.replace(/\px/g, "")
}
document.onmousemove = function (e) {
const titleH = dialogHeaderEl.offsetHeight;
// 通过事件委托,计算移动的距离
let l = e.clientX - disX;
let t = e.clientY - disY;
// 移动边界处理
if (t < 0 && (t + styMT + styT) <= 0 || t < 0 && (styMT + styT) <= 0) {
t = -(styMT + styT);
} else if (t > 0 && t > (document.body.clientHeight - styMT - styT - titleH)) {
t = document.body.clientHeight - styMT - styT - titleH;
}
// 移动当前元素
dragDom.style.left = `${l + styL}px`;
dragDom.style.top = `${t + styT}px`;
};
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
};
dialogHeaderEl.onmousedown = moveDown;
dragDom.onmousemove = function (e) {
const dialogBODY = el.querySelector(".el-dialog__body");
const resizeDom = el.querySelector(".resize");
const titleH = dialogHeaderEl.offsetHeight;
dragDom.onmousedown = e => {
const clientX = e.clientX;
const clientY = e.clientY;
let elW = dragDom.clientWidth;
let elH = dragDom.clientHeight;
let EloffsetLeft = dragDom.offsetLeft;
let EloffsetTop = dragDom.offsetTop;
dragDom.style.userSelect = "none";
let ELscrollTop = el.scrollTop;
let resizeW = resizeDom.clientWidth, resizeH = resizeDom.clientHeight;
//判断点击的位置是不是为头部
if (
clientX > EloffsetLeft &&
clientX < EloffsetLeft + elW &&
clientY > EloffsetTop &&
clientY < EloffsetTop + 100
) {
//如果是头部
} else {
document.onmousemove = function (e) {
e.preventDefault(); // 移动时禁用默认事件
//鼠标拖拽
if (
clientX > EloffsetLeft + elW - resizeW &&
clientX < EloffsetLeft + elW
) {
//往左拖拽
if (clientX > e.clientX) {
if (dragDom.clientWidth < minWidth) {
} else {
dragDom.style.width = elW - (clientX - e.clientX) * 2 + "px";
}
}
//往右拖拽
if (clientX <= e.clientX) {
let targetTW = elW + (e.clientX - clientX) * 2
targetTW > windowW ?
dragDom.style.width = windowW + "px" :
dragDom.style.width = targetTW + "px"
}
}
//底部鼠标拖拽位置
if (
ELscrollTop + clientY > EloffsetTop + elH - resizeH &&
ELscrollTop + clientY < EloffsetTop + elH
) {
//往上拖拽
if (clientY > e.clientY) {
if (dragDom.clientHeight < minHeight) {
} else {
dragDom.style.height = elH - (clientY - e.clientY) * 1 + "px";
dialogBODY.style.height = elH - (clientY - e.clientY) * 1 - titleH + "px";
}
}
//往下拖拽
if (clientY <= e.clientY) {
e.clientY >= windowH ?
dragDom.style.height = windowH - dragDom.offsetTop + "px" :
dragDom.style.height = elH + (e.clientY - clientY) * 1 + "px";
dialogBODY.style.height = elH - (clientY - e.clientY) * 1 - titleH + "px";
}
}
};
//结束
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
}
};
};
}
});
export default Vue.directive('dialogDrag')