驎驎 發表於 2020-2-17 19:25:00

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) =&gt;<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) =&gt; getComputedStyle(dom, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">)
      }
    })()

    dialogHeaderEl.onmousedown </span>= (e) =&gt;<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) &gt;<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 &gt;<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) &gt;<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 &gt;<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 &lt; 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) =&gt;<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 &gt; content.offsetWidth &amp;&amp; height &lt;<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 &lt; content.offsetWidth &amp;&amp; height &gt;<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 &lt; content.offsetWidth &amp;&amp; height &lt;<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>&lt;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"&gt;
      &lt;div class="dialog-body"&gt;
          &lt;div class="line"&gt;
            &lt;slot name="content"&gt;&lt;/slot&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;slot slot="footer" class="dialog-footer"&gt;&lt;/slot&gt;
      &lt;/el-dialog&gt;</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>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/Bree/p/12323171.html
頁: [1]
查看完整版本: elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题