element-ui 的 dialog 实现拖拽、水平伸缩、双击头部放大

2023-11-02

import Vue from 'vue';

/*
 *  使用:
 *  elementUI 的 dialog 上加上 v-dialogDrag 指令就可以实现弹窗的全屏和拉伸了。
 *  给 dialog 设置 :close-on-click-modal="false" , 禁止点击遮罩层关闭弹出层
 *  如果是 form 表单,不要将提交等按钮放置 el-form-item,以免在上下拉伸时被隐藏
 */

// v-dialogDrag: 弹窗拖拽+水平方向伸缩
Vue.directive('dialogDrag', {
  bind(el, binding, vnode, oldVnode) {
    //弹框可拉伸最小宽高
    const minWidth = 400;
    const 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);

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

      // 获取到的值带px 正则匹配替换
      let styL;
      let 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;
      }
    };

    dragDom.onmousemove = function (e) {
      const moveE = e;
      if (e.clientX > dragDom.offsetLeft + dragDom.clientWidth - 10) {
        dragDom.style.cursor = 'e-resize';
      } else if (dragDom.offsetLeft + 10 > e.clientX) {
        dragDom.style.cursor = 'w-resize';
      } else if (el.scrollTop + e.clientY > dragDom.offsetTop + dragDom.clientHeight - 10) {
        dragDom.style.cursor = 's-resize';
      } else {
        dragDom.style.cursor = 'default';
        dragDom.onmousedown = null;
      }

      dragDom.onmousedown = (e) => {
        const clientX = e.clientX;
        const clientY = e.clientY;
        const elW = dragDom.clientWidth;
        const elH = dragDom.clientHeight;
        const EloffsetLeft = dragDom.offsetLeft;
        const EloffsetTop = dragDom.offsetTop;
        dragDom.style.userSelect = 'none';
        const ELscrollTop = el.scrollTop;

        //判断点击的位置是不是为头部
        if (
          clientX > EloffsetLeft &&
          clientX < EloffsetLeft + elW &&
          clientY > EloffsetTop &&
          clientY < EloffsetTop + 100
        ) {
          //如果是头部在此就不做任何动作,以上有绑定dialogHeaderEl.onmousedown = moveDown;
        } else {
          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`;
                }
              }
            }

            //右侧鼠标拖拽位置
            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`;
              }
            }

            //底部鼠标拖拽位置
            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;
          };
        }
      };
    };
  },
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

element-ui 的 dialog 实现拖拽、水平伸缩、双击头部放大 的相关文章

  • Vue校验时报Cannot read property ‘validate’ of undefined错误

    Error in v on handler TypeError Cannot read properties of undefined reading validate 解决 1 传值的时候 要带引号
  • 项目 和 api 接口说明文档

    注意 所有api的域名为 http 如果后面文档中 有的域名地址和这里不一样 以这里的为主 获取图文资讯 地址 api getnewlist 作用描述 主要用来获取点击首页上的 新闻资讯 后进入到的图文列表页面的数据 大家在做的时候可以使用
  • Vue开发环境搭建和vue-cli脚手架

    vue本质是一个js脚本 提供了一个前端框架 在开发时 可以直接引入这个js脚本 也可以使用脚手架工具 在本地搭建一个项目 Vue js安装 方法一 在 Vue js 的官网上直接下载 vue min js 并用
  • element-ui 的 dialog 实现拖拽、水平伸缩、双击头部放大

    import Vue from vue 使用 elementUI 的 dialog 上加上 v dialogDrag 指令就可以实现弹窗的全屏和拉伸了 给 dialog 设置 close on click modal false 禁止点击遮
  • vue正式环境与测试环境压包配置方法

    1 安装cross env cnpm install save dev cross env package json配置修改 这里分别添加env config prod env config dev来控制当前的压包环境 package js
  • vue自定义穿梭框支持远程滚动加载

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 分享一个使用比较久的 技术框架公司的选型 老项目 vue2 iview ui 方案的实现思路是共性的 展现UI样式需要你们自定义进行更改 因为iview是全局注入
  • vscode下载和安装教程和配置中文插件(超详细)

    目录 前言必读 一 下载步骤 二 安装步骤 vscode安装设置完成 三 安装中文插件 额外的 四 设置vue高亮代码 额外的 前言必读 读者手册 必读 云边的快乐猫的博客 CSDN博客 前言 vscode主要是用于前端的编程工具 其他编程
  • ant design Table实现可编辑的单元格

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 分享一个使用比较久的 需求 最近接到的一个需求 在table栏中实现属性的可编辑单元格 并且table内部可动态删减的单元格 外部操作新增或删除一行新旧数据的操作
  • vue2 使用 Sortable 库进行拖拽操作

    一 vue 项目使用 文档地址 https www itxst com sortablejs neuinffi html 1 安装依赖 npm i S vuedraggable 2 vue 文件引入组件 import draggable f
  • 浅谈require和import

    最近在学习webpack时候 教程上用到的是require 但是之前我写代码用的Import比较多 所以借这个机会来学习一下 node编程中最重要的思想就是模块化 import和require都是被模块化所使用 遵循规范 require 是
  • URL 链接中 井号#、问号?、连接符& 分别有什么作用?

    井号 表示网页中的一个位置 被称之为锚点 常用于某个网页间不同位置的跳转 简单的说就是在一个网页中 URL 不变的情况下 通过添加 buy 的字符在 URL 最后可以跳转到当前网页中已经定义好的锚点 id buy 位置 同样 的改变也会增加
  • 前端优秀插件网站汇总整理——轻松建站。。。

    1 Amaze Ui 妹子UI 中国首个html5跨屏前端框架 http amazeui org 2 WebUploader 一个简单的以HTML5为主 FLASH为辅的现代文件上传组件 http fex baidu com webuplo
  • Node.js到底是什么?

    前言 Node js是一个基于Chrome V8引擎的JavaScript运行环境 JavaScript是脚本语言 脚本语言需要一个解析器 运行环境 才能运行 若运行在浏览器中 则浏览器就是JavaScript的解析器 运行环境 而对于独立
  • 阿里云图标使用 (symbol 引用方式)

    阿里云图标网址 https www iconfont cn 一 登录注册 这个简单 就不说了 二 给当前项目找图库 2 1 添加项目 2 2 寻找图标添加入库 添加入库 2 3 打开入库 的图标添加到指定项目 添加到当前项目 1 2 三 项
  • vue2引入Element UI组件去创建新页面的详细步骤--项目阶段2

    目录 一 Element UI介绍 Element UI的特点 二 下载配置Element UI 零 创建vue项目 一 下载Element UI依赖 二 全局文件main js中引入Element UI 三 删除多余的东西 一 删除App
  • 关于echarts 图,在切换tab后,返回时宽度变窄的问题

    项目场景 提示 这里简述项目相关背景 最近在做一个统计报表的项目 需要插入ECharts 图表和表格做统计 并且可以导出Excel 表格 问题描述 提示 这里描述项目中遇到的问题 在开发过程中 碰到了一个 echarts 图在切换到 tab
  • vue-element-admin+flask实现数据查询项目

    本文分享一个使用vue element admin flask实现的一个数据查询项目 填写数据库连接信息和查询语句 即可展示查询到的数据 前提 已下载vue element admin并编译成功 前端 1 添加路由 src router i
  • vue组件库的开发流程

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 开发流程 1 创建项目 vue cli 公司现有架构 2 调整项目静态目录结构 3 使用webpack相关库模式打包编译 4 使用npm或者公司源地址发布到你需要的
  • canvas绘制一个圆分成六等分颜色随机

  • 前端push.js桌面通知库

    push js 官网 https pushjs org 安装 1 npm 安装方式 npm install push js save 2 script引入方式 使用 1 获取用户许可 用户需要先授予权限才能发送通知 Push Permiss

随机推荐