div拖拽移动—改变大小尺寸

159 阅读1分钟
<template>
  <div
    class="floating-window-wrap"
    ref="floatingWindow"
    draggable="false"
    @mousedown="down"
  >
    <img
      class="qr-code"
      src="../assets/img/hycr.png"
      @contextmenu="() => false"
      draggable="false"
      alt=""
    />
  </div>
</template>

<script>
import { toRefs, reactive, ref, onMounted } from "vue";
export default {
  name: "FloatingWindow",
  props: {
    image: {
      type: String,
      required: true,
    },
  },
  setup(props, context) {
    console.log(props);

    // 数据中心
    const data = reactive({});

    // 组件实例
    const floatingWindow = ref(null);
    let FWDom = null;

    // 挂在元素完成后
    onMounted(() => {
      FWDom = floatingWindow.value;
      floatingWindowInit();
    });

    // 是否开启尺寸修改
    let resizeable = false;
    // 鼠标按下时的坐标,并在修改尺寸时保存上一个鼠标的位置
    let clientX, clientY;
    // div可修改的最小宽高
    let minW = 8, minH = 8;
    // 鼠标按下时的位置,使用n、s、w、e表示
    let direc = "";

    // 浮窗初始化
    function floatingWindowInit() {
      // body监听鼠标(移动事件 | 松开事件)
      document.body.addEventListener("mousemove", move);
      document.body.addEventListener("mouseup", up);
    }

    // 鼠标松开时结束尺寸修改
    function up() {
      resizeable = false;
    }

    // 鼠标按下时开启尺寸修改
    function down(e) {
      let d = getDirection(e);
      // 当位置为四个边和四个角时才开启尺寸修改
      if (d !== "") {
        resizeable = true;
        direc = d;
        clientX = e.clientX;
        clientY = e.clientY;
      }else{
        // let odiv = e.target; // 获取目标元素
        //计算出鼠标相对点击元素的位置,e.clientX获取的是鼠标的位置,OffsetLeft是元素相对于外层元素的位置
        let x = e.clientX - FWDom.offsetLeft;
        let y = e.clientY - FWDom.offsetTop;
        document.onmousemove = (e) => {
          // 获取拖拽元素的位置
          let left = e.clientX - x;
          let top = e.clientY - y;
          // this.positionX = left;
          // this.positionY = top;
          //console.log(document.documentElement.clientHeight,odiv.offsetHeight)
          // 把拖拽元素 放到 当前的位置
          if (left <= 0) {
            left = 0;
          } else if (
            left >=
            document.documentElement.clientWidth - FWDom.offsetWidth
          ) {
            //document.documentElement.clientWidth 屏幕的可视宽度
            left = document.documentElement.clientWidth - FWDom.offsetWidth - 1;
          }

          if (top <= 0) {
            top = 0;
          } else if (
            top >=
            document.documentElement.clientHeight - FWDom.offsetHeight
          ) {
            // document.documentElement.clientHeight 屏幕的可视高度
            top = document.documentElement.clientHeight - FWDom.offsetHeight - 1;
          }
          FWDom.style.left = left + "px";
          FWDom.style.top = top + "px";
        };
        // 为了防止 火狐浏览器 拖拽阴影问题
        document.onmouseup = (e) => {
          document.onmousemove = null;
          document.onmouseup = null;
        };
      }
    }

    // 鼠标移动事件
    function move(e) {
      let d = getDirection(e);
      let cursor;
      if (d === "") cursor = "default";
      else cursor = d + "-resize";
      if (cursor !== FWDom.style.cursor) {
        // 修改鼠标显示效果
        FWDom.style.cursor = cursor;
        console.log(4534);
      }
      // 当开启尺寸修改时,鼠标移动会修改div尺寸
      if (resizeable) {
        // 鼠标按下的位置在右边,修改宽度
        if (direc.indexOf("e") !== -1) {
          FWDom.style.width =
            Math.max(minW, FWDom.offsetWidth + (e.clientX - clientX)) + "px";
          clientX = e.clientX;
        }

        // 鼠标按下的位置在上部,修改高度
        if (direc.indexOf("n") !== -1) {
          FWDom.style.height =
            Math.max(minH, FWDom.offsetHeight + (clientY - e.clientY)) + "px";
          clientY = e.clientY;
        }
        // 鼠标按下的位置在底部,修改高度
        if (direc.indexOf("s") !== -1) {
          FWDom.style.height =
            Math.max(minH, FWDom.offsetHeight + (e.clientY - clientY)) + "px";
          clientY = e.clientY;
        }

        // 鼠标按下的位置在左边,修改宽度
        if (direc.indexOf("w") !== -1) {
          FWDom.style.width =
            Math.max(minW, FWDom.offsetWidth + (clientX - e.clientX)) + "px";
          clientX = e.clientX;
        }

        if (direc === "se") {
          FWDom.style.width =
            Math.max(minW, FWDom.offsetWidth + (e.clientX - clientX)) + "px";
          clientX = e.clientX;
          FWDom.style.height =
            Math.max(minH, FWDom.offsetHeight + (e.clientY - clientY)) + "px";
          clientY = e.clientY;
        }
      }
    }

    // 获取鼠标所在div的位置
    function getDirection(ev) {
      let xP, yP, offset, dir;
      dir = "";

      xP = ev.offsetX;
      yP = ev.offsetY;
      offset = 10;

      if (yP < offset) dir += "n";
      else if (yP > FWDom.offsetHeight - offset) dir += "s";
      if (xP < offset) dir += "w";
      else if (xP > FWDom.offsetWidth - offset) dir += "e";
      console.log(dir);
      return dir;
    }


    return {
      ...toRefs(data),
      ...toRefs(props),
      floatingWindow,
      down,
    };
  },
};
</script>

<style lang="less">
.floating-window-wrap {
  width: 300px;
  height: 300px;
  box-sizing: border-box;

  // background-color: rgba(255, 0, 0, 0.3);
  position: fixed;
  top: 0;
  left: 0;

  border: 3px solid rgb(236, 65, 65);
  padding: 10px;

  -moz-user-select: -moz-none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -o-user-select: none;
  user-select: none;

  .qr-code {
    width: 100%;
    height: 100%;
    -moz-user-select: -moz-none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    -o-user-select: none;
    user-select: none;

    cursor: move;
  }
}
</style>