zoukankan      html  css  js  c++  java
  • 简单实现el-dialog的拖拽功能

    首先还是要明确几个概念,这里通过修改css并截图给大家介绍下,理解了这几个概念,代码写起来会得心应手许多。

    • clientWidth,clientHeight
    • scrollWidth,scrollHeight
    • offsetWidth,offsetHeight
    • clientLeft,clientTop
    • scrollLeft,scrollTop
    • offsetLeft,offsetTop

    1. clientWidth,clientHeight

    clientWidth,clientHeight表示对象内容的可视区的宽度,不包括滚动条和边框,会随对象显示大小的变化而改变。


    上图中,我给el-scrollbar__view这个div增加了10px的红色边框,整个div的实际高度,宽度变成了3452px,1920px,观察clientWidth,clientHeight的值是3432px,1900px,并没有包含边框和滚动条的宽度。

    2. scrollWidth,scrollHeight

    scrollWidth,scrollHeight表示对象的实际内容的宽度,不包括边框(但是包括滚动条),会随对象中内容超过可视区后而变大。

     

    上图中,我还是给el-scrollbar__view这个div增加了10px的红色边框,整个div的实际高度,宽度变成了3452px,1920px,观察scrollWidth,scrollHeight的值是3432px,1900px,并没有包含边框的宽度。

    3. offsetWidth,offsetHeight

    offsetWidth,offsetHeight表示对象整体的实际宽度,包括滚动条和边框,会随对象显示大小的变化而改变。

     上图中,我还是给el-scrollbar__view这个div增加了10px的红色边框,整个div的实际高度,宽度变成了3452px,1920px,观察scrollWidth,scrollHeight的值仍然是3452px,1920px,包含滚动条和边框。

    4. clientLeft,clientTop

    clientLeft,clientTop表示对象边框的宽度。

     上图中,我还是给el-scrollbar__view这个div增加了10px的红色边框,观察clientLeft, clientTop均为10px。

    5. scrollLeft,scrollTop

    scrollLeft,scrollTop表示对象的显示(可见)的内容与该对象实际的内容的距离。

     上图中,我们给content这个section设置了宽高均是300px,并设置显示滚动条,将滚动条拖动一部分,观察scrollLeft,scrollTop的值分别是164px,204px,这对应着当前内容距离原来实际内容的距离(假设蓝色框是实际内容的距离)。

    6. offsetLeft,offsetTop

    offsetLeft,offsetTop表示对象边框的外边缘距离与已定位的父容器(offsetparent)的内边距离(不包括元素的边框和父容器的边框)。

     
    上图中,el-dialog这个div距离已定位的父容器(这里是el-dialog__wrapper)的宽高分别是672px,61px,与offsetLeft,offsetTop值一致。
     
     
    我们给el-dialog__wrapper加上一个20px的黄色边框,给el-dialog加上一个10px的蓝色边框,再来观察offsetLeft,offsetTop的值,发现在计算时,是从黄色边框的内边距到蓝色边框的外边距,不包括边框。

    7. coding

    明确上述概念之后,我们来着手写代码,先说下我的业务场景。
    有一个dialog弹框,弹框的背景并不是全屏的,只在除header,sidebar的地方显示,要求拖拽dialog弹框不能超过背景。
    我们在main.js同级目录创建directives.js,具体代码如下

     1 import Vue from 'vue';
     2 
     3 // v-dialogDrag 弹窗拖拽
     4 Vue.directive('dialogDrag', {
     5     bind(el, binding, vnode, oldVnode) {
     6         const dialogHeaderEl = el.querySelector('.el-dialog__header');
     7         const dragDom = el.querySelector('.el-dialog');
     8         dialogHeaderEl.style.cursor = 'move';
     9         // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    10         const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
    11         dialogHeaderEl.onmousedown = (e) => {
    12             console.log('屏幕高度', document.documentElement.clientHeight);
    13             console.log('弹窗高度', dragDom.offsetHeight);
    14             // 鼠标按下,获取鼠标在盒子内的坐标
    15             const disX = e.clientX - dialogHeaderEl.offsetLeft;
    16             const disY = e.clientY - dialogHeaderEl.offsetTop;
    17             // 获取到的值带px 正则匹配替换
    18             let styL;
    19             let styT;
    20             // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
    21             if (sty.left.includes('%')) {
    22                 styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
    23                 styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
    24             } else {
    25                 styL = +sty.left.replace(/px/g, '');
    26                 styT = +sty.top.replace(/px/g, '');
    27             }
    28             // 鼠标移动的时候,把鼠标在页面中的坐标,减去鼠标在盒子内的坐标就是模态框的left和top值
    29             document.onmousemove = function(e) {
    30                 // 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离)
    31                 const l = e.clientX - disX;
    32                 const t = e.clientY - disY;
    33 
    34                 let finallyL = l + styL;
    35                 let finallyT = t + styT;
    36 
    37                 // 边界值判定 注意clientWidth scrollWidth区别 要减去之前的top left值
    38                 let limitL = (document.documentElement.clientWidth - dragDom.clientWidth) / 2;
    39                 if (finallyL < -limitL) {
    40                     finallyL = -limitL;
    41                 } else if (finallyL > limitL) {
    42                     finallyL = limitL;
    43                 }
    44                 let limitT = document.documentElement.clientHeight * 15 / 100;
    45                 let limitB = document.documentElement.clientHeight - dragDom.clientHeight - limitT;
    46                 if (finallyT < -limitT) {
    47                     finallyT = -limitT;
    48                 } else if (finallyT > limitB) {
    49                     finallyT = limitB;
    50                 }
    51                 // 移动当前元素
    52                 dragDom.style.left = `${finallyL}px`;
    53                 dragDom.style.top = `${finallyT}px`;
    54             };
    55             document.onmouseup = function(e) {
    56                 document.onmousemove = null;
    57                 document.onmouseup = null;
    58             };
    59         };
    60     }
    61 });

    参考网址:https://www.jianshu.com/p/c3ce06c423af?tdsourcetag=s_pctim_aiomsg

  • 相关阅读:
    nginx 命令
    nginx 配置文件(windows)
    nginx 配置文件(linux)
    nginx 安装
    什么是REST架构
    名词解释
    建造者模式
    单例模式
    工厂模式
    赋值运算符,拷贝构造函数,clone()方法总结
  • 原文地址:https://www.cnblogs.com/guwufeiyang/p/13230116.html
Copyright © 2011-2022 走看看