elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题
<p>1、首先在vue项目中创建一个js文件eg:dialog.js</p><div class="cnblogs_code">
<pre>import Vue from 'vue'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> v-dialogDrag: 弹窗拖拽属性</span>
Vue.directive('dialogDrag'<span style="color: rgba(0, 0, 0, 1)">, {
bind (el, binding, vnode, oldVnode) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自定义属性,判断是否可拖拽 </span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (!binding.value) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">
const dialogHeaderEl </span>= el.querySelector('.el-dialog__header'<span style="color: rgba(0, 0, 0, 1)">)
const dragDom </span>= el.querySelector('.el-dialog'<span style="color: rgba(0, 0, 0, 1)">)
dialogHeaderEl.style.cssText </span>+= ';cursor:move;'<span style="color: rgba(0, 0, 0, 1)">
dragDom.style.cssText </span>+= ';top:0px;'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);</span>
const sty = (<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (document.body.currentStyle) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在ie下兼容写法</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> (dom, attr) =><span style="color: rgba(0, 0, 0, 1)"> dom.currentStyle
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> (dom, attr) => getComputedStyle(dom, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">)
}
})()
dialogHeaderEl.onmousedown </span>= (e) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 鼠标按下,计算当前元素距离可视区的距离</span>
const disX = e.clientX -<span style="color: rgba(0, 0, 0, 1)"> dialogHeaderEl.offsetLeft
const disY </span>= e.clientY -<span style="color: rgba(0, 0, 0, 1)"> dialogHeaderEl.offsetTop
const screenWidth </span>= document.body.clientWidth <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> body当前宽度</span>
const screenHeight = document.documentElement.clientHeight <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可见区域高度(应为body高度,可某些环境下无法获取)</span>
<span style="color: rgba(0, 0, 0, 1)">
const dragDomWidth </span>= dragDom.offsetWidth <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 对话框宽度</span>
const dragDomheight = dragDom.offsetHeight <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 对话框高度</span>
<span style="color: rgba(0, 0, 0, 1)">
const minDragDomLeft </span>=<span style="color: rgba(0, 0, 0, 1)"> dragDom.offsetLeft
const maxDragDomLeft </span>= screenWidth - dragDom.offsetLeft -<span style="color: rgba(0, 0, 0, 1)"> dragDomWidth
const minDragDomTop </span>=<span style="color: rgba(0, 0, 0, 1)"> dragDom.offsetTop
const maxDragDomTop </span>= screenHeight - dragDom.offsetTop -<span style="color: rgba(0, 0, 0, 1)"> dragDomheight
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取到的值带px 正则匹配替换</span>
let styL = sty(dragDom, 'left'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为兼容ie </span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (styL === 'auto') styL = '0px'<span style="color: rgba(0, 0, 0, 1)">
let styT </span>= sty(dragDom, 'top'<span style="color: rgba(0, 0, 0, 1)">)
console.log(styL)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (styL.includes('%'<span style="color: rgba(0, 0, 0, 1)">)) {
styL </span>= +document.body.clientWidth * (+styL.replace(/%/g, '') / 100<span style="color: rgba(0, 0, 0, 1)">)
styT </span>= +document.body.clientHeight * (+styT.replace(/%/g, '') / 100<span style="color: rgba(0, 0, 0, 1)">)
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
styL </span>= +styL.replace(/px/g, ''<span style="color: rgba(0, 0, 0, 1)">)
styT </span>= +styT.replace(/px/g, ''<span style="color: rgba(0, 0, 0, 1)">)
};
document.onmousemove </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (e) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过事件委托,计算移动的距离</span>
let left = e.clientX -<span style="color: rgba(0, 0, 0, 1)"> disX
let top </span>= e.clientY -<span style="color: rgba(0, 0, 0, 1)"> disY
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 边界处理</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (-(left) ><span style="color: rgba(0, 0, 0, 1)"> minDragDomLeft) {
left </span>= -<span style="color: rgba(0, 0, 0, 1)">(minDragDomLeft)
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (left ><span style="color: rgba(0, 0, 0, 1)"> maxDragDomLeft) {
left </span>=<span style="color: rgba(0, 0, 0, 1)"> maxDragDomLeft
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (-(top) ><span style="color: rgba(0, 0, 0, 1)"> minDragDomTop) {
top </span>= -<span style="color: rgba(0, 0, 0, 1)">(minDragDomTop)
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (top ><span style="color: rgba(0, 0, 0, 1)"> maxDragDomTop) {
top </span>=<span style="color: rgba(0, 0, 0, 1)"> maxDragDomTop
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 移动当前元素</span>
dragDom.style.cssText += `;left:${left + styL}px;top:${top +<span style="color: rgba(0, 0, 0, 1)"> styT}px;`
}
document.onmouseup </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (e) {
document.onmousemove </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
document.onmouseup </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
}
})
Vue.directive(</span>'dialogChange'<span style="color: rgba(0, 0, 0, 1)">, {
bind (el, binding, vnode, oldVnode) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自定义属性,判断是否可拉伸</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (!binding.value) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">
const dragDom </span>= el.querySelector('.el-dialog'<span style="color: rgba(0, 0, 0, 1)">)
let dragMouse
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在弹出框的右下角添加可拉伸标志 class='mouse'</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i < dragDom.childNodes.childNodes.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (dragDom.childNodes.childNodes.className === 'mouse'<span style="color: rgba(0, 0, 0, 1)">) {
dragMouse </span>= dragDom.childNodes.childNodes
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 鼠标拖拽</span>
dragMouse.onmousedown = (e) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> content区域</span>
const content =<span style="color: rgba(0, 0, 0, 1)"> dragDom.parentNode.parentNode.parentNode.parentNode
const disX </span>= e.clientX -<span style="color: rgba(0, 0, 0, 1)"> dragDom.offsetWidth
const disY </span>= e.clientY -<span style="color: rgba(0, 0, 0, 1)"> dragDom.offsetHeight
document.onmousemove </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (e) {
e.preventDefault() </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 移动时禁用默认事件</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过事件委托,计算移动的距离</span>
let width = e.clientX -<span style="color: rgba(0, 0, 0, 1)"> disX
let height </span>= e.clientY -<span style="color: rgba(0, 0, 0, 1)"> disY
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (width > content.offsetWidth && height <<span style="color: rgba(0, 0, 0, 1)"> content.offsetHeight) {
dragDom.style.height </span>=<span style="color: rgba(0, 0, 0, 1)"> `${height}px`
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (width < content.offsetWidth && height ><span style="color: rgba(0, 0, 0, 1)"> content.offsetHeight) {
dragDom.style.width </span>=<span style="color: rgba(0, 0, 0, 1)"> `${width}px`
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (width < content.offsetWidth && height <<span style="color: rgba(0, 0, 0, 1)"> content.offsetHeight) {
dragDom.style.width </span>=<span style="color: rgba(0, 0, 0, 1)"> `${width}px`
dragDom.style.height </span>=<span style="color: rgba(0, 0, 0, 1)"> `${height}px`
}
}
document.onmouseup </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (e) {
document.onmousemove </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
document.onmouseup </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
}
})</span></pre>
</div>
<p>2、在main.js中引用</p>
<div class="cnblogs_code">
<pre>import './components/dialog'</pre>
</div>
<p>3、dialog组件 代码中添加v-if为了让每次弹出框都不继承上一次的改变:</p>
<div class="cnblogs_code">
<pre><el-<span style="color: rgba(0, 0, 0, 1)">dialog
v</span>-<span style="color: rgba(0, 0, 255, 1)">if</span>=<span style="color: rgba(0, 0, 0, 1)">dialog.dialogVisible
v</span>-dialogDrag:{dialogDrag}=<span style="color: rgba(0, 0, 0, 1)">dialog.dialogDrag
v</span>-dialogChange:{dialogChange}=<span style="color: rgba(0, 0, 0, 1)">dialog.dialogChange
ref</span>="dialog__wrapper"<span style="color: rgba(0, 0, 0, 1)">
:close</span>-on-click-modal="false"<span style="color: rgba(0, 0, 0, 1)">
:title</span>=<span style="color: rgba(0, 0, 0, 1)">dialog.title
:visible.sync</span>="dialog.dialogVisible"<span style="color: rgba(0, 0, 0, 1)">
:before</span>-close="handleClose">
<div class="dialog-body">
<div class="line">
<slot name="content"></slot>
</div>
</div>
<slot slot="footer" class="dialog-footer"></slot>
</el-dialog></pre>
</div>
<p>4、在引用组件时, data返回一个:</p>
<div class="cnblogs_code">
<pre>dialog: {<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> dialog显示隐藏</span>
dialogVisible: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
dialogDrag: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可拖拽</span>
dialogChange: <span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可拉伸</span>
title: '详情'<span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/Bree/p/12323171.html
頁:
[1]