Vue realizes opening multiple draggable pop-up windows

        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>

Guess you like

Origin blog.csdn.net/weixin_46205984/article/details/130405788