其他分享
首页 > 其他分享> > vue.js:拖动四个角及四个边来改变选区大小并移动(vue@3.2.36)

vue.js:拖动四个角及四个边来改变选区大小并移动(vue@3.2.36)

作者:互联网

一,js代码:

<template>
  <div style="background: #ffffff;" id="root" @mousemove="onMove" @mouseup="onEnd">
    <div id="wrapper" style="position: relative;width:300px;overflow: hidden;margin-left:100px;margin-top:30px;" >
      <img id="img" src="static/image/back@2x.jpg" style="width:300px;display: block;" />

      <div id="mask" class="mask" @mousedown="maskDown" >

        <div id="coor_tl" class="coor_tl" @mousedown="coormousedown_tl"  ></div>
        <div id="coor_tm" class="coor_tm" @mousedown="coormousedown_tm"   ></div>
        <div id="coor_tr" class="coor_tr" @mousedown="coormousedown_tr"   ></div>

        <div id="coor_ml" class="coor_ml" @mousedown="coormousedown_ml"  ></div>
        <div id="coor_mr" class="coor_mr" @mousedown="coormousedown_mr"  ></div>

        <div id="coor_bl" class="coor_bl" @mousedown="coormousedown_bl"  ></div>
        <div id="coor_bm" class="coor_bm" @mousedown="coormousedown_bm"   ></div>
        <div id="coor_br" class="coor_br" @mousedown="coormousedown_br"   ></div>
      </div>

    </div>
  </div>
</template>

<script>
import {onMounted, ref} from "vue"
export default {
  name: "DragImg",
  setup() {
    // 当前操作的类型,标记当前要拖动的区域
    const operateType = ref("");

    //记录点击时的x位置
    const clickX = ref(0);
    //记录点击时的y位置
    const clickY = ref(0);

    //从event中得到位置
    const getLocation = (e) => {
      return {
        x: e.x || e.clientX,
        y: e.y || e.clientY
      }
    }

    //容器的位置x
    const wrapper_x = ref(0);
    //容器的位置y
    const wrapper_y = ref(0);
    //容器的宽度
    const wrapper_w = ref(0);
    //容器的高度
    const wrapper_h = ref(0);

    //鼠标在coor上面按下时的处理函数
    const onDragDown = (e, type) => {
      e.stopPropagation();
      console.log("begin onDragDown");

      origin_w.value = document.getElementById('mask').getBoundingClientRect().width;
      origin_h.value = document.getElementById('mask').getBoundingClientRect().height;

      origin_x.value = document.getElementById('mask').getBoundingClientRect().left;
      origin_y.value = document.getElementById('mask').getBoundingClientRect().top;

      wrapper_x.value = document.getElementById('wrapper').getBoundingClientRect().left;
      wrapper_y.value = document.getElementById('wrapper').getBoundingClientRect().top;

      wrapper_w.value = document.getElementById('wrapper').getBoundingClientRect().width;
      wrapper_h.value = document.getElementById('wrapper').getBoundingClientRect().height;

      var location = getLocation(e);
      clickY.value = location.y;
      clickX.value = location.x;
      operateType.value = type;
      return false;
    };

    //鼠标松开时的事件
    const onDragUp = () => {
      document.body.style.cursor = "auto";
      operateType.value = null;
    };
    //coor鼠标按下:底部左侧
    const coormousedown_bl = (e) => {
      onDragDown(e, "bl");
    };
    //coor鼠标按下:底部中间
    const coormousedown_bm = (e) => {
      onDragDown(e, "b");
    };
    //coor鼠标按下:底部右侧
    const coormousedown_br = (e) => {
      onDragDown(e, "br");
    };
    //coor鼠标按下:顶部左侧
    const coormousedown_tl = (e) => {
      onDragDown(e, "tl");
    };
    //coor鼠标按下:顶部中间
    const coormousedown_tm = (e) => {
      onDragDown(e, "t");
    };
    //coor鼠标按下:顶部右侧
    const coormousedown_tr = (e) => {
      onDragDown(e, "tr");
    };
    //coor鼠标按下:中部左侧
    const coormousedown_ml = (e) => {
      onDragDown(e, "l");
    };
    //coor鼠标按下:中部右侧
    const coormousedown_mr = (e) => {
      onDragDown(e, "r");
    };

    //coor,向右侧拖动
    const setMoveR = (location) => {
      let mask = document.getElementById('mask');
      var disHe = location.x - clickX.value;
      //console.log("disHe:"+disHe);
      var widthe = origin_w.value+disHe;
      //console.log("origin_x:"+origin_x.value+";wrapper_w:"+wrapper_w.value);
      if (((origin_x.value-wrapper_x.value)+widthe) > wrapper_w.value) {
        widthe = wrapper_w.value-(origin_x.value-wrapper_x.value);
      }

      mask.style.width =  widthe+ 'px';
    }
    //coor,向底部拖动
    const setMoveB = (location) => {
      let mask = document.getElementById('mask');
      var disVs = location.y - clickY.value;
      //console.log("disVs:"+disVs);
      var heights = (origin_h.value+disVs);
      if (((origin_y.value-wrapper_y.value)+heights) > wrapper_h.value) {
        heights = wrapper_h.value-(origin_y.value-wrapper_y.value);
      }

      mask.style.height = heights + 'px';
    }
    //coor,向左侧拖动
    const setMoveL = (location,disX) => {
      let mask = document.getElementById('mask');
      //console.log("disX:"+disX);
      if (disX >= 0) {
        var disH = location.x - clickX.value;
        //console.log("disH:"+disH);
        var widthw = origin_w.value-disH;
        //console.log("location.x:"+location.x+";clickX.value:"+clickX.value+";origin_w.value:"+origin_w.value+";widthw:"+widthw);
        mask.style.width =  widthw+ 'px';
      }

      if (disX >= 0) {
        mask.style.left = disX + 'px';
      } else {
        mask.style.left =  '0px';
      }
    }

    //coor,向顶部拖动
    const setMoveT = (location,disY) => {
      let mask = document.getElementById('mask');
      //console.log("disY:"+disY);
      if (disY >= 0) {
        var disV = location.y - clickY.value;
        var heightn = origin_h.value - disV;
        //console.log("location.y:" + location.y + ";clickY.value:" + clickY.value + ";origin_h.value:" + origin_h.value + ";heightn:" + heightn);
        mask.style.height = heightn + 'px';
      }
      if (disY >= 0) {
        mask.style.top = disY + 'px';
      } else {
        mask.style.top =  '0px';
      }
    }

    //mask可以移动到的最右位置
    const rightMax = ref(0);
    //mask可以移动到的最下位置
    const bottomMax = ref(0);

    //移动mask的方法
    const setMoveMask = (location) => {

      var nx = location.x;
      var ny = location.y;
      //计算移动后的左偏移量和顶部的偏移量
      var nl = nx - (clickX.value - origin_x.value) - wrapper_x.value;
      var nt = ny - (clickY.value - origin_y.value) - wrapper_y.value;

      if (nl < 0) {
        nl = 0;
      }
      if (nl > rightMax.value) {
        nl = rightMax.value;
      }
      if (nt < 0) {
        nt = 0;
      }
      if (nt > bottomMax.value) {
        nt = bottomMax.value;
      }

      document.getElementById("mask").style.left = nl + 'px';
      document.getElementById("mask").style.top = nt + 'px';
    }

    //鼠标移动的通用处理方法
    const move = (operateType, location) => {
      let disY = (origin_y.value + (location.y - clickY.value))-wrapper_y.value;
      let disX = (origin_x.value + (location.x - clickX.value))-wrapper_x.value;

      switch (operateType) {
        case "r":
          setMoveR(location);
          break;
        case "b":
          setMoveB(location);
          break;
        case "l":
          setMoveL(location,disX);
          break;
        case "t":
          setMoveT(location,disY);
          break;
        case "br":
          setMoveB(location);
          setMoveR(location);
          break;
        case "tr":
          setMoveT(location,disY);
          setMoveR(location);
          break;
        case "tl":
          setMoveT(location,disY);
          setMoveL(location,disX);
          break;
        case "bl":
          setMoveB(location);
          setMoveL(location,disX);
          break;
        case "mask":
          setMoveMask(location);
          break;
      }
    };

    //当页面中鼠标移动时触发
    const onDragMove = (e) => {
        var location = getLocation(e);
        switch (operateType.value) {
          case "t":
            move("t", location);
            break;
          case "b":
            move("b", location);
            break;
          case "l":
            move("l", location);
            break;
          case "r":
            move("r", location);
            break;
          case "tl":
            move("tl", location);
            break;
          case "tr":
            move("tr", location);
            break;
          case "bl":
            move("bl", location);
            break;
          case "br":
            move("br", location);
            break;
          case "mask":
            move("mask", location);
            break;
        }
      return false;
    };

    //mask的宽度
    const origin_w = ref(0);
    //mask的高度
    const origin_h = ref(0);
    //mask的x
    const origin_x = ref(0);
    //mask的y
    const origin_y = ref(0);

    // mounted,页面加载成功的生命周期
    onMounted(()=>{
      document.onmousemove = onDragMove;
      document.onmouseup = onDragUp;
    })

    //当鼠标在mask区域中按下时触发
    const maskDown = (e) => {
      console.log("-------------------maskdown begin");
      var location = getLocation(e);
      clickY.value = location.y;
      clickX.value = location.x;

      operateType.value = 'mask';

      origin_w.value = document.getElementById('mask').getBoundingClientRect().width;
      origin_h.value = document.getElementById('mask').getBoundingClientRect().height;

      origin_x.value = document.getElementById('mask').getBoundingClientRect().left;
      origin_y.value = document.getElementById('mask').getBoundingClientRect().top;

      wrapper_x.value = document.getElementById('wrapper').getBoundingClientRect().left;
      wrapper_y.value = document.getElementById('wrapper').getBoundingClientRect().top;

      wrapper_w.value = document.getElementById('wrapper').getBoundingClientRect().width;
      wrapper_h.value = document.getElementById('wrapper').getBoundingClientRect().height;

      rightMax.value = wrapper_w.value-origin_w.value;
      bottomMax.value = wrapper_h.value-origin_h.value;
    }

    return {
      coormousedown_bl,
      coormousedown_bm,
      coormousedown_br,

      coormousedown_tl,
      coormousedown_tm,
      coormousedown_tr,

      coormousedown_ml,
      coormousedown_mr,
      onDragUp,

      maskDown,
    }
  }
}
</script>

<style scoped>

.coor_ml {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  left: 0; top: calc(50% - 5px);
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:w-resize;
}

.coor_mr {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  right: 0; top: calc(50% - 5px);
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:e-resize;
}

.coor_tl {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  left: 0; top: 0;
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:nw-resize;
}

.coor_tm {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  left: calc(50% - 5px); top: 0;
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:n-resize;
}

.coor_tr {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  right: 0; top: 0;
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:ne-resize;
}

.coor_bl {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  left: 0; bottom: 0;
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:sw-resize;
}

.coor_bm {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  left: calc(50% - 5px); bottom: 0;
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:s-resize;
}

.coor_br {
  width: 10px;
  height: 10px;
  overflow: hidden;
  position: absolute;
  right: 0; bottom: 0;
  background-color: #ffFFFF;
  opacity: 0.2;
  z-index: 5000;
  cursor:se-resize;
}

.mask {
  position: absolute;
  width:100px;
  height:100px;
  left:50px;
  top:250px;
  box-shadow: 0 0 0 999vw rgba(0, 0, 0, .5);
}
</style>

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/
         或: https://gitee.com/liuhongdi

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,测试效果

三,查看vue.js的版本:

liuhongdi@lhdpc:/data/vue/imgtouch$ npm list vue
imgtouch@0.1.0 /data/vue/imgtouch
├─┬ @vue/cli-plugin-babel@5.0.4
│ └─┬ @vue/babel-preset-app@5.0.4
│   └── vue@3.2.36 deduped
├─┬ element-plus@2.2.2
│ ├─┬ @element-plus/icons-vue@1.1.4
│ │ └── vue@3.2.36 deduped
│ ├─┬ @vueuse/core@8.6.0
│ │ ├─┬ @vueuse/shared@8.6.0
│ │ │ └── vue@3.2.36 deduped
│ │ ├─┬ vue-demi@0.13.1
│ │ │ └── vue@3.2.36 deduped
│ │ └── vue@3.2.36 deduped
│ └── vue@3.2.36 deduped
└─┬ vue@3.2.36
  └─┬ @vue/server-renderer@3.2.36
    └── vue@3.2.36 deduped

 

标签:origin,vue,const,mask,边来,value,location,四个,wrapper
来源: https://www.cnblogs.com/architectforest/p/16355214.html