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: '详情'
}
转载于//www.cnblogs.com/Lu-Lu/p/11168904.html
还没有评论,来说两句吧...