指令实现element弹窗的全屏与移动

注意点

  • 在弹窗外加一层div,指令加在div上,不要直接加在弹窗上,会报错
    在这里插入图片描述
  • 在指令上给弹窗加一个高度,用vh单位,加高度是为了计算后续的移动边界
  • 全屏状态下不允许移动
 <div v-drag="'40vh'">
   <el-dialog ref="dialogRef"   v-model="open"   title="Tips"  :close-on-click-modal="false">
    ....
   </el-dialog>
 </div>

效果

在这里插入图片描述

代码

/加载需要的样式
require("./drag.scss");

let value = (el, binding) => {
  console.log("绑定的值:", binding);
  //弹窗
  let dialog = document.getElementsByClassName("el-dialog")[0];
  console.log("弹窗", dialog);

  //初始化不最大化
  el.fullscreen = false;

  //获取弹窗的初始宽高,这里不设置默认高度,设置默认高度会影响页面的样式
  let defaultWidth = dialog.style.width;
  let defaultHeight = (dialog.style.height = binding.value || "50vh");
  console.log("默认宽高:", defaultWidth, defaultWidth);

  //设置弹窗初始边距,以弹窗左上角为起始点,后面的边界计算以此为基础
  dialog.style.left = "0px";
  dialog.style.top = "0px";

  //获取弹窗头,加上放大,缩小图标
  let dialogHeader = document.getElementsByClassName("el-dialog__header")[0];
  //修改鼠标移入表头的样式
  dialogHeader.classList.add("move_dialog");
  //修改弹窗表头样式
  dialogHeader.classList.add("dialog_header");
  //防止标题被选中
  dialogHeader.onselectstart = () => false;

  //通过输出表头,可以看出关闭按钮是一个button
  console.log("表头", dialogHeader);
  let maxOrMinList = document.getElementsByClassName("max_or_min");

  //防止重复添加
  let maxOrMin = document.createElement("button");
  //放大、缩小按
  maxOrMin.className += "el-dialog__headerbtn max_or_min";
  maxOrMin.innerHTML = `<i class="el-icon-full-screen"/></i>`;

  //给按钮添加事件,实现放大和缩小
  maxOrMin.onclick = () => {
    if (el.fullscreen) {
      //缩小
      dialog.style.marginTop = "15vh";
      dialog.style.width = defaultWidth;
      // dialog.style.height = "auto";
      maxOrMin.innerHTML = `<i class="el-icon-full-screen"/></i>`;
    } else {
      //放大
      dialog.style.marginTop = "10vh";
      dialog.style.width = "90%";
      dialog.style.top = "0px";
      maxOrMin.innerHTML = `<i class="el-icon-copy-document"/></i>`;
    }
    el.fullscreen = !el.fullscreen;
  };

  if (maxOrMinList.length == 0) {
    //将按钮插入弹窗头部
    dialogHeader.appendChild(maxOrMin);
  }

  //鼠标拖动,给表头添加事件
  //鼠标拖拽,必须是在鼠标按下之后,松开之前进行
  dialogHeader.onmousedown = (ev) => {
    //全屏时不允许拖拽
    if (el.fullscreen) {
      return false;
    }

    //获取点击时鼠标的坐标
    let dx = ev.clientX || ev.pageX;
    let dy = ev.clientY || ev.pageY;

    //定义一个开关,默认鼠标点击之后开启
    let flag = true;
    //绑定鼠标移动事件,要在全屏移动,所以用绑定document
    document.onmousemove = (e) => {
      if (flag) {
        /** **********************横向移动********************** */
        //横向移动距离
        let moveLeft = parseInt(dialog.style.left);
        //屏幕宽高
        let windowWidth = document.documentElement.clientWidth;

        //计算横向移动范围,屏幕宽度*(100% - 弹窗宽度)*0.5
        let rangeLeft =
          windowWidth * (100 - parseInt(dialog.style.width)) * -0.005;
        let rangeRight =
          windowWidth * (100 - parseInt(dialog.style.width)) * 0.005;
        console.log("横向范围:", rangeLeft, rangeRight);
        console.log("横向:", e.movementX);
        if (moveLeft > rangeLeft && moveLeft <= rangeRight) {
          dialog.style.left = moveLeft + e.movementX + "px";
        } else if (moveLeft <= rangeLeft) {
          dialog.style.left = rangeLeft + 1 + "px";
        } else if (moveLeft >= rangeRight) {
          dialog.style.left = rangeRight - 1 + "px";
        }

        /** *****************************纵向移动************************** */
        //纵向移动距离
        let moveTop = parseInt(dialog.style.top);
        //屏幕宽高
        let windowHeight = document.documentElement.clientHeight;
        //计算纵向移动距离,乘以0.15是因为,弹窗默认距离顶部的距离是15%
        let rangeTop = windowHeight * -0.15;
        //向下距离是屏幕高度-弹窗距离顶部高度-弹窗高度
        let rangeBottom =
          windowHeight * (100 - 15 - parseInt(dialog.style.height)) * 0.01;
        console.log("纵向范围:", rangeBottom, rangeTop);
        console.log("纵向:", e.movementY, moveTop); //往上是负值
        if (moveTop < rangeBottom && moveTop > rangeTop) {
          dialog.style.top = moveTop + e.movementY + "px";
        } else if (moveTop >= rangeBottom) {
          dialog.style.top = rangeBottom - 1 + "px";
        } else if (moveTop <= rangeTop) {
          dialog.style.top = rangeTop + 1 + "px";
        }
        console.log(dialog.style.top, rangeTop);
      }
    };
    document.onmouseup = () => {
      flag = false;
    };
  };
};

export default {
  name: "drag",
  mounted: value,
  updated: value,
};
// 放大缩小按钮样式
.max_or_min {
  color: #909399;
  margin-right: 30px;
  font-size: 15px;
}

// 平移样式,鼠标悬浮到弹窗头部,改变鼠标样式
.move_dialog:hover {
  cursor: move;
}

// 弹窗表头样式
.dialog_header {
  background-color: #e9e9e9;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无知的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值