Jamey's Jamey's
首页
导航站
  • 学习专栏

    • 《HTML》笔记
    • 《CSS》笔记
    • 《JavaScript》笔记
    • 《Vue》笔记
    • 《Git》笔记
    • 《规范》笔记
    • 《软技能》笔记
    • 《面试》笔记
    • 《持续集成&交付&部署》笔记
  • 踩坑专栏

    • 《Element-UI 实践系列》笔记
    • 《移动端 实践系列》笔记
    • 《综合》笔记
  • 配置专栏

    • 《环境系列》笔记
  • 极空间

    • Docker
  • 影视

    • movie
  • 编辑器笔记

    • 开发编辑器
  • 浏览器笔记

    • Chrome
  • Mac笔记

    • Mac
  • 跨界学习

    • 运营
  • 破解合集

    • 破解
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 书单
    • 关于

Jamey

首页
导航站
  • 学习专栏

    • 《HTML》笔记
    • 《CSS》笔记
    • 《JavaScript》笔记
    • 《Vue》笔记
    • 《Git》笔记
    • 《规范》笔记
    • 《软技能》笔记
    • 《面试》笔记
    • 《持续集成&交付&部署》笔记
  • 踩坑专栏

    • 《Element-UI 实践系列》笔记
    • 《移动端 实践系列》笔记
    • 《综合》笔记
  • 配置专栏

    • 《环境系列》笔记
  • 极空间

    • Docker
  • 影视

    • movie
  • 编辑器笔记

    • 开发编辑器
  • 浏览器笔记

    • Chrome
  • Mac笔记

    • Mac
  • 跨界学习

    • 运营
  • 破解合集

    • 破解
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 书单
    • 关于
  • 二次封装

  • 实践踩坑

    • Icon图标

    • Table表格

    • Checkbox多选框

    • Message消息提示

    • Dialog对话框

      • 高度固定方案
      • 拖拽,全屏,拉宽高等功能指令
        • 一. 问题
        • 二. 解决办法
    • Input输入框

    • Tree树形控件

  • 《Element-UI 实践系列》笔记
  • 实践踩坑
  • Dialog对话框
Jamey
2022-07-08
目录

拖拽,全屏,拉宽高等功能指令

# 拖拽,全屏,拉宽高等功能指令

# 一. 问题

使用网上的 el-dialog 的拖拽指令拉宽指令,存在如下问题

  1. 使用指令后 el-table 的头部的可伸缩时的鼠标样式会消失
  2. 使用指令后 el-dialog 的内容不能文本复制了(这个影响最大)

# 二. 解决办法

经过本人研究,特定组合了指令方~~~~法完美地解决了 el-dialog 的拖拽,双击头部放大,拉宽拉高等功能,而且没有后遗症(el-dialog 的内容不能文本复制,el-table 的头部拉宽时的鼠标样式会显示问题)

/*
 *  定义公共 js 里,在入口文件 main.js 中 import;
 *  给 elementUI 的 dialog 上加上 v-dialogDrag 指令就可以实现弹窗的全屏和拉伸了。
 */
// v-dialogDrag: 弹窗拖拽 + 水平方向伸缩
Vue.directive('dialogDrag', {
  bind(el, binding, vnode, oldVnode) {
    // 弹框可拉伸最小宽高
    let minWidth = 400;
    let minHeight = 300;
    // 初始非全屏
    let isFullScreen = false;
    // 当前宽高
    let nowWidth = 0;
    let nowHight = 0;
    // 当前顶部高度
    let nowMarginTop = 0;
    // 获取弹框头部(这部分可双击全屏)
    const dialogHeaderEl = el.querySelector('.el-dialog__header');
    //弹窗
    const dragDom = el.querySelector('.el-dialog');
    // 给弹窗加上 overflow auto;不然缩小时框内的标签可能超出 dialog;
    dragDom.style.overflow = "auto";
    // 清除选择头部文字效果
    dialogHeaderEl.onselectstart = new Function("return false");  
    // 头部加上可拖动 cursor
    dialogHeaderEl.style.cursor = 'move';

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);

    let moveDown = (e) => {
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft;
      const disY = e.clientY - dialogHeaderEl.offsetTop;

      // 获取到的值带 px 正则匹配替换
      let styL, styT;

      // 注意在 ie 中 第一次获取到的值为组件自带 50% 移动之后赋值为 px
      if (sty.left.includes('%')) {
        styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
        styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
      } else {
        styL = +sty.left.replace(/\px/g, '');
        styT = +sty.top.replace(/\px/g, '');
      };

      document.onmousemove = function (e) {
        // 通过事件委托,计算移动的距离 
        const l = e.clientX - disX;
        const t = e.clientY - disY;

        // 移动当前元素  
        dragDom.style.left = `${l + styL}px`;
        dragDom.style.top = `${t + styT}px`;

        // 将此时的位置传出去
        // binding.value({x:e.pageX,y:e.pageY})
      };

      document.onmouseup = function (e) {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    }
    dialogHeaderEl.onmousedown = moveDown;
    // 双击头部效果
    dialogHeaderEl.ondblclick = (e) => {
      if (isFullScreen == false) {
        nowHight = dragDom.clientHeight;
        nowWidth = dragDom.clientWidth;
        nowMarginTop = dragDom.style.marginTop;
        dragDom.style.left = 0;
        dragDom.style.top = 0;
        dragDom.style.height = "100VH";
        dragDom.style.width = "100VW";
        dragDom.style.marginTop = 0;
        isFullScreen = true;
        dialogHeaderEl.style.cursor = 'initial';
        dialogHeaderEl.onmousedown = null;
      } else {
        dragDom.style.height = "auto";
        dragDom.style.width = nowWidth + 'px';
        dragDom.style.marginTop = nowMarginTop;
        isFullScreen = false;
        dialogHeaderEl.style.cursor = 'move';
        dialogHeaderEl.onmousedown = moveDown;
      }
    }
    
    // 拉伸(右下方)
    let resizeEl=document.createElement("div");
    dragDom.appendChild(resizeEl); 
    // 在弹窗右下角加上一个 10-10px 的控制块
    resizeEl.style.cursor = 'se-resize';
    resizeEl.style.position = 'absolute';
    resizeEl.style.height = '10px';
    resizeEl.style.width = '10px';
    resizeEl.style.right = '0px';
    resizeEl.style.bottom = '0px';
    resizeEl.style.zIndex = '99';
    //鼠标拉伸弹窗
    resizeEl.onmousedown = (e) => {
      // 记录初始 x 位置
      let clientX = e.clientX;
      // 鼠标按下,计算当前元素距离可视区的距离
      let disX = e.clientX - resizeEl.offsetLeft;
      let disY = e.clientY - resizeEl.offsetTop;

      document.onmousemove = function (e) {
        e.preventDefault(); // 移动时禁用默认事件
        
        // 通过事件委托,计算移动的距离
        let x = e.clientX - disX + (e.clientX - clientX);// 这里 由于 elementUI 的 dialog 控制居中的,所以水平拉伸效果是双倍
        let y = e.clientY - disY;
        // 比较是否小于最小宽高
        dragDom.style.width = x > minWidth ? `${x}px` : minWidth + 'px';
        dragDom.style.height = y > minHeight ? `${y}px` : minHeight + 'px';
        };
      // 拉伸结束
      document.onmouseup = function (e) {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    }
    
    // 拉伸(右边)
    let resizeElR=document.createElement("div");
    dragDom.appendChild(resizeElR); 
    // 在弹窗右下角加上一个10-10px的控制块
    resizeElR.style.cursor = 'w-resize';
    resizeElR.style.position = 'absolute';
    resizeElR.style.height = '100%';
    resizeElR.style.width = '10px';
    resizeElR.style.right = '0px';
    resizeElR.style.top = '0px';
    // 鼠标拉伸弹窗
    resizeElR.onmousedown = (e) => {
      let elW = dragDom.clientWidth;
      let EloffsetLeft = dragDom.offsetLeft;
      // 记录初始x位置
      let clientX = e.clientX;
      document.onmousemove = function (e) {
        e.preventDefault(); // 移动时禁用默认事件
        // 右侧鼠标拖拽位置
        if (clientX > EloffsetLeft + elW - 10 && clientX < EloffsetLeft + elW) {
            // 往左拖拽
            if (clientX > e.clientX) {
                if (dragDom.clientWidth < minWidth) {
                } else {
                    dragDom.style.width = elW - (clientX - e.clientX) * 2 + 'px';
                }
            }
            // 往右拖拽
            if (clientX < e.clientX) {
                dragDom.style.width = elW + (e.clientX - clientX) * 2 + 'px';
            }
        }
       
      };
      // 拉伸结束
      document.onmouseup = function (e) {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    }
    
    // 拉伸(左边)
    let resizeElL=document.createElement("div");
    dragDom.appendChild(resizeElL); 
    // 在弹窗右下角加上一个10-10px的控制块
    resizeElL.style.cursor = 'w-resize';
    resizeElL.style.position = 'absolute';
    resizeElL.style.height = '100%';
    resizeElL.style.width = '10px';
    resizeElL.style.left = '0px';
    resizeElL.style.top = '0px';
    // 鼠标拉伸弹窗
    resizeElL.onmousedown = (e) => {
      let elW = dragDom.clientWidth;
      let EloffsetLeft = dragDom.offsetLeft;
      // 记录初始x位置
      let clientX = e.clientX;
      document.onmousemove = function (e) {
        e.preventDefault(); // 移动时禁用默认事件
        // 左侧鼠标拖拽位置
        if (clientX > EloffsetLeft && clientX < EloffsetLeft + 10) {
            // 往左拖拽
            if (clientX > e.clientX) {
                dragDom.style.width = elW + (clientX - e.clientX) * 2 + 'px';
            }
            // 往右拖拽
            if (clientX < e.clientX) {
                if (dragDom.clientWidth < minWidth) {
                } else {
                    dragDom.style.width = elW - (e.clientX - clientX) * 2 + 'px';
        
                }
            }
        }
       
      };
      // 拉伸结束
      document.onmouseup = function (e) {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    }
    
    // 拉伸(下边)
    let resizeElB=document.createElement("div");
    dragDom.appendChild(resizeElB); 
    // 在弹窗右下角加上一个 10-10px 的控制块
    resizeElB.style.cursor = 'n-resize';
    resizeElB.style.position = 'absolute';
    resizeElB.style.height = '10px';
    resizeElB.style.width = '100%';
    resizeElB.style.left = '0px';
    resizeElB.style.bottom = '0px';
    // 鼠标拉伸弹窗
    resizeElB.onmousedown = (e) => {
     let EloffsetTop = dragDom.offsetTop;
     let ELscrollTop = el.scrollTop;
      let clientY = e.clientY;
      let elH = dragDom.clientHeight;
      document.onmousemove = function (e) {
        e.preventDefault(); // 移动时禁用默认事件
        // 底部鼠标拖拽位置
        if (ELscrollTop + clientY > EloffsetTop + elH - 20 && ELscrollTop + clientY < EloffsetTop + elH) {
            // 往上拖拽
            if (clientY > e.clientY) {
                if (dragDom.clientHeight < minHeight) {
                } else {
                    dragDom.style.height = elH - (clientY - e.clientY) * 2 + 'px';
                }
            }
            // 往下拖拽
            if (clientY < e.clientY) {
                dragDom.style.height = elH + (e.clientY - clientY) * 2 + 'px';
            }
        }
      };
      // 拉伸结束
      document.onmouseup = function (e) {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    }
  }
})
/**
 *  注意:如果是 el-dialog 弹出的表单 el-form,最好不要把提交按钮当做 el-form-item(elementUI 文档是这么用的),放在el-dialog里。
 *  不然按钮会同 el-dialog 中标签一样被 overflow;
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#Element
上次更新: 2022/07/08, 17:40:08
高度固定方案
限制输入方案

← 高度固定方案 限制输入方案→

Theme by Vdoing | Copyright © 2017-2023 Jamey | blog 闽ICP备19022664号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式