There are many online tutorials to realize the draggable function, and I need to click on the page to open multiple draggable pop-up boxes on this basis.
First execute the following command to install vuedraggable, and it is better to realize the drag transition animation through vuedraggable.
npm install vuedraggable --save
Create a new dialogDrag.js file with the following contents:
import Vue from 'vue'
Vue.directive('dialogDrag', {
bind(el) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cursor = 'move'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
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, styT
// 注意在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, '')
}
document.onmousemove = function(e) {
// 获取body的页面可视宽高
// var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
// var clientWidth = document.documentElement.clientWidth || document.body.clientWidth
// 通过事件委托,计算移动的距离
var l = e.clientX - disX
var t = e.clientY - disY
// 边界处理
if (-l > minDragDomLeft) {
l = -minDragDomLeft
} else if (l > maxDragDomLeft) {
l = maxDragDomLeft
}
if (-t > minDragDomTop) {
t = -minDragDomTop
} else if (t > maxDragDomTop) {
t = maxDragDomTop
}
// 移动当前元素
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
// 将此时的位置传出去
// binding.value({x:e.pageX,y:e.pageY})
}
document.onmouseup = function() {
document.onmousemove = null
document.onmouseup = null
}
}
}
})
Bind to the component through the v-dialogDrag command in the page to achieve the drag effect.
<el-dialog
v-dialogDrag //绑定拖动效果
:title="title"
:lock-scroll="false"
:close-on-press-escape="false"
:visible.sync="dialogVisible"
width="30%"
:append-to-body="true" // 解决弹窗关不掉或者在弹窗框上层多出一个遮罩层的问题
destroy-on-close>
<el-image :src="imageUrl"></el-image>
</el-dialog>
At this point, the draggable effect of the pop-up window frame has been realized.
But it has not met my needs. Next, I need to realize that the pop-up box can be opened to continue to operate the page. The pop-up box has a mask layer by default, you need to close the mask layer, and close the Dialog by clicking the modal.
<el-dialog
v-dialogDrag //绑定拖动效果
:title="title"
:lock-scroll="false"
:close-on-press-escape="false"
:visible.sync="dialogVisible"
width="30%"
:append-to-body="true" // 解决弹窗关不掉或者在弹窗框上层多出一个遮罩层的问题
:close-on-click-modal="false" //关闭通过点击 modal 关闭 Dialog
:modal="false" // 关闭遮罩层
destroy-on-close>
<el-image :src="imageUrl"></el-image>
</el-dialog>
Next, you can continue to click on the page after opening the pop-up window.
Just add the css style below.
.el-dialog__wrapper {
pointer-events: none;
}
.el-dialog {
pointer-events:auto;
}
Note: The css style must be written in the right position, otherwise it will not take effect, because the .el-dialog style is not effective, so write the .el-dialog style into the dialogDrag.js culture.
The final code is as follows:
import Vue from 'vue'
// v-dialogDrag: 弹窗拖拽
Vue.directive('dialogDrag', {
bind(el) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cursor = 'move'
// 重点!!!!解决打开多个弹窗后,弹窗失去拖动功能
// .el-dialog样式
dragDom.style.pointerEvents = 'auto';
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
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, styT
// 注意在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, '')
}
document.onmousemove = function(e) {
// 获取body的页面可视宽高
// var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
// var clientWidth = document.documentElement.clientWidth || document.body.clientWidth
// 通过事件委托,计算移动的距离
var l = e.clientX - disX
var t = e.clientY - disY
// 边界处理
if (-l > minDragDomLeft) {
l = -minDragDomLeft
} else if (l > maxDragDomLeft) {
l = maxDragDomLeft
}
if (-t > minDragDomTop) {
t = -minDragDomTop
} else if (t > maxDragDomTop) {
t = maxDragDomTop
}
// 移动当前元素
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
// 将此时的位置传出去
// binding.value({x:e.pageX,y:e.pageY})
}
document.onmouseup = function() {
document.onmousemove = null
document.onmouseup = null
}
}
}
})
<template>
<div class="dd_class_div">
<el-dialog
v-dialogDrag //绑定拖动效果
:title="title"
:lock-scroll="false"
:close-on-press-escape="false"
:visible.sync="dialogVisible"
width="30%"
:append-to-body="true" // 解决弹窗关不掉或者在弹窗框上层多出一个遮罩层的问题
:close-on-click-modal="false" //关闭通过点击 modal 关闭 Dialog
:modal="false" // 关闭遮罩层
destroy-on-close>
<el-image :src="imageUrl"></el-image>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'draggableDialog',
data() {
return {
dialogVisible:false,
imageUrl:'',
title:''
}
},
methods: {
dialogClose(){
this.dialogVisible = false;
}
}
}
</script>
<style scoped>
.el-dialog__wrapper{
pointer-events: none;
}
.dd_class_div {
text-align: center;
}
</style>