ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-06-08 12:31:10  阅读:179  来源: 互联网

标签:origin vue const mask 边来 value location 四个 wrapper


一,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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有