zoukankan      html  css  js  c++  java
  • elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题

    开发完后台管理系统的弹出框模块,被添加拖拽和拉伸功能,看了很多网上成熟的帖子引到项目里总有一点问题,下面是根据自己的需求实现的步骤:

    首先在vue项目中创建一个js文件eg:dialog.js

      1 import Vue from 'vue'
      2 // v-dialogDrag: 弹窗拖拽属性
      3 Vue.directive('dialogDrag', {
      4   bind (el, binding, vnode, oldVnode) {
         // 自定义属性,判断是否可拖拽 
    5 if (!binding.value) return 6 const dialogHeaderEl = el.querySelector('.el-dialog__header') 7 const dragDom = el.querySelector('.el-dialog') 8 dialogHeaderEl.style.cssText += ';cursor:move;' 9 dragDom.style.cssText += ';top:0px;' 10 11 // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); 12 const sty = (function () { 13 if (document.body.currentStyle) { 14 // 在ie下兼容写法 15 return (dom, attr) => dom.currentStyle[attr] 16 } else { 17 return (dom, attr) => getComputedStyle(dom, false)[attr] 18 } 19 })() 20 21 dialogHeaderEl.onmousedown = (e) => { 22 // 鼠标按下,计算当前元素距离可视区的距离 23 const disX = e.clientX - dialogHeaderEl.offsetLeft 24 const disY = e.clientY - dialogHeaderEl.offsetTop 25 26 const screenWidth = document.body.clientWidth // body当前宽度 27 const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取) 28 29 const dragDomWidth = dragDom.offsetWidth // 对话框宽度 30 const dragDomheight = dragDom.offsetHeight // 对话框高度 31 32 const minDragDomLeft = dragDom.offsetLeft 33 const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth 34 35 const minDragDomTop = dragDom.offsetTop 36 const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight 37 38 // 获取到的值带px 正则匹配替换 39 let styL = sty(dragDom, 'left')
         // 为兼容ie 
    40 if (styL === 'auto') styL = '0px' 41 let styT = sty(dragDom, 'top') 42 43 console.log(styL) 44 // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px 45 if (styL.includes('%')) { 46 styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100) 47 styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100) 48 } else { 49 styL = +styL.replace(/px/g, '') 50 styT = +styT.replace(/px/g, '') 51 }; 52 53 document.onmousemove = function (e) { 54 55 // 通过事件委托,计算移动的距离 56 let left = e.clientX - disX 57 let top = e.clientY - disY 58 // 边界处理 59 if (-(left) > minDragDomLeft) { 60 left = -(minDragDomLeft) 61 } else if (left > maxDragDomLeft) { 62 left = maxDragDomLeft 63 } 64 65 if (-(top) > minDragDomTop) { 66 top = -(minDragDomTop) 67 } else if (top > maxDragDomTop) { 68 top = maxDragDomTop 69 } 70 71 // 移动当前元素 72 dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;` 73 } 74 75 document.onmouseup = function (e) { 76 document.onmousemove = null 77 document.onmouseup = null 78 } 79 return false 80 } 81 } 82 }) 83 84 Vue.directive('dialogChange', { 85 bind (el, binding, vnode, oldVnode) {
         // 自定义属性,判断是否可拉伸
    86 if (!binding.value) return 87 const dragDom = el.querySelector('.el-dialog') 88 let dragMouse 89 // 在弹出框的右下角添加可拉伸标志 class='mouse' 95 for (let i = 0; i < dragDom.childNodes[2].childNodes.length; i++) { 96 if (dragDom.childNodes[2].childNodes[i].className === 'mouse') { 97 dragMouse = dragDom.childNodes[2].childNodes[i] 98 } 99 } 100 // 鼠标拖拽 101 dragMouse.onmousedown = (e) => { 102 // content区域 103 const content = dragDom.parentNode.parentNode.parentNode.parentNode 104 const disX = e.clientX - dragDom.offsetWidth 105 const disY = e.clientY - dragDom.offsetHeight 106 107 document.onmousemove = function (e) { 108 e.preventDefault() // 移动时禁用默认事件 109 // 通过事件委托,计算移动的距离 110 let width = e.clientX - disX 111 let height = e.clientY - disY 112 113 if (width > content.offsetWidth && height < content.offsetHeight) { 114 dragDom.style.height = `${height}px` 115 } else if (width < content.offsetWidth && height > content.offsetHeight) { 116 dragDom.style.width = `${width}px` 117 } else if (width < content.offsetWidth && height < content.offsetHeight) { 118 dragDom.style.width = `${width}px` 119 dragDom.style.height = `${height}px` 120 } 121 } 122 document.onmouseup = function (e) { 123 document.onmousemove = null 124 document.onmouseup = null 125 } 126 return false 127 } 128 } 129 })

    在main.js中引用

    import './components/dialog'

    dialog组件 代码中添加v-if为了让每次弹出框都不继承上一次的改变:

     1     <el-dialog
     2         v-if=dialog.dialogVisible
     3         v-dialogDrag:{dialogDrag}=dialog.dialogDrag
     4         v-dialogChange:{dialogChange}=dialog.dialogChange
     5         ref="dialog__wrapper"
     6         :close-on-click-modal="false"
     7         :title=dialog.title
     8         :visible.sync="dialog.dialogVisible"
     9         :before-close="handleClose">
    10         <div class="dialog-body">
    11           <div class="line">
    12             <slot name="content"></slot>
    13           </div>
    14         </div>
    15         <slot slot="footer" class="dialog-footer"></slot>
    16       </el-dialog>

    在引用组件时, data返回一个:

        dialog: {// dialog显示隐藏
            dialogVisible: false,
            dialogDrag: true, // 可拖拽
            dialogChange: true, // 可拉伸
            title: '详情'
          }
  • 相关阅读:
    java实现Floyd算法
    java实现Floyd算法
    java实现Floyd算法
    java实现Floyd算法
    java实现Dijkstra算法
    java实现Dijkstra算法
    java实现Dijkstra算法
    java实现Dijkstra算法
    java实现Dijkstra算法
    QTableWidget简单应用之文件浏览器
  • 原文地址:https://www.cnblogs.com/Lu-Lu/p/11168904.html
Copyright © 2011-2022 走看看