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