当前位置: 首页 > news >正文

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: '详情'
      }

 

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

相关文章:

  • 小程序开发过程中常见问题[微信小程序、支付宝小程序]
  • 变量引用的错误:UnboundLocalError: local variable 'range' referenced before assignment
  • 解决docker镜像无法下载的问题
  • java8时间类的一些封装
  • 3.appium环境搭建(原理)
  • 69期-Java SE-025-动态代理
  • JavaScript数值处理 + 小花样
  • SQLMap使用总结
  • Redis 学习笔记(篇五):对象(RedisObject)
  • Codevs 3981 动态最大子段和
  • A 小石的签到题
  • 又是问题~~~
  • Sql: 請假跨月份問題,或跨年份問題 日期部分边界
  • OpenFlow通信流程解读
  • React 入门与实战-课时7 虚拟DOM的本质和目的
  • 【Leetcode】104. 二叉树的最大深度
  • 【知识碎片】第三方登录弹窗效果
  • classpath对获取配置文件的影响
  • Magento 1.x 中文订单打印乱码
  • vue2.0项目引入element-ui
  • 产品三维模型在线预览
  • 力扣(LeetCode)56
  • 前端面试之闭包
  • 思否第一天
  • 算法-插入排序
  • 新手搭建网站的主要流程
  • 学习JavaScript数据结构与算法 — 树
  • 阿里云移动端播放器高级功能介绍
  • ​力扣解法汇总946-验证栈序列
  • # Apache SeaTunnel 究竟是什么?
  • # include “ “ 和 # include < >两者的区别
  • #define 用法
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (6)STL算法之转换
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (汇总)os模块以及shutil模块对文件的操作
  • (剑指Offer)面试题34:丑数
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)linux下的时间函数使用
  • (转)德国人的记事本
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .CSS-hover 的解释
  • .dwp和.webpart的区别
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • :如何用SQL脚本保存存储过程返回的结果集
  • @angular/cli项目构建--Dynamic.Form
  • @ComponentScan比较
  • @RequestBody的使用
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具