elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题

落日映苍穹つ 2021-11-27 03:08 632阅读 0赞

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

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

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

在main.js中引用

  1. import './components/dialog'

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

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

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

  1. dialog: {
  2. // dialog显示隐藏
  3. dialogVisible: false,
  4. dialogDrag: true, // 可拖拽
  5. dialogChange: true, // 可拉伸
  6. title: '详情'
  7. }

转载于:https://www.cnblogs.com/Lu-Lu/p/11168904.html

发表评论

表情:
评论列表 (有 0 条评论,632人围观)

还没有评论,来说两句吧...

相关阅读