200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > vue拖动缩放组件(vue-drag-zoom) 增加禁止缩放拖拽功能

vue拖动缩放组件(vue-drag-zoom) 增加禁止缩放拖拽功能

时间:2022-03-27 15:31:23

相关推荐

vue拖动缩放组件(vue-drag-zoom) 增加禁止缩放拖拽功能

前段时间写了一个类似于百度ICOR,可拖拽缩放图片并在图片上框选文字的功能,这里的拖拽缩放功能就用到了vue-drag-zoom组件,组件是从npm下载的VUE2代码,放在VUE3+vite项目里面也是可以兼容的,但是组件仅提供了禁止缩放的API且存在一定问题

附npm地址:vue-drag-zoom - npm该组件适用于对一个元素在某个区域内进行拖动/缩放. Latest version: 1.0.9, last published: 4 months ago. Start using vue-drag-zoom in your project by running `npm i vue-drag-zoom`. There are no other projects in the npm registry using vue-drag-zoom./package/vue-drag-zoom

以下为改造后源码:

1.新增禁止拖拽API,与禁止缩放API整合

2.解决了缩放后图片不固定在中心点问题

3.解决了频繁禁止与恢复拖拽缩放时,图片回到初始位置的问题

<template><div ref="xx-drag-zoom" class="xx-drag-zoom" :style="dragZoomNodeStyle"><slot></slot></div></template><script>export default {name: "xx-drag-zoom",components: {},props: {/* 被操作的元素 start */// X 坐标left: {type: Number,default: 0,},// Y 坐标top: {type: Number,default: 0,},// 宽度width: Number,// 高度height: Number,// 允许缩放allowZoom: Boolean,// 缩放比例zoom: {type: Number,default: 1,},// 最大缩放比例maxZoom: {type: Number,default: 2,},// 最小缩放比例minZoom: {type: Number,default: 0.5,},// 缩放幅度range: {type: Number,default: 0.1,},/* 被操作的元素 end *//* 活动区域 start */// 节点 (注: 传入节点后可以自动获取数据, 不需要再传坐标与宽高了)areaNode: HTMLDivElement,// X 坐标 (未设置 areaNode 时生效)areaLeft: {type: Number,default: 0,},// Y 坐标 (未设置 areaNode 时生效)areaTop: {type: Number,default: 0,},// 宽度 (未设置 areaNode 时生效)areaWidth: {type: Number,default: 200,},// 高度 (未设置 areaNode 时生效)areaHeight: {type: Number,default: 100,},/* 活动区域 end */},data() {return {currentZoom: this.zoom,initLeft: this.left,initTop: this.top,lastPosition: {},};},computed: {// 被操作的元素节点dragZoomNode() {return this.$refs["xx-drag-zoom"];},// 活动区域数据areaNodeData() {let obj = {};// 计算属性无法监听活动区域的宽高变化const node = this.areaNode;if (node) {obj = {left: node.clientLeft, //活动区域定位 ? 左边框宽度top: node.clientTop,width: node.offsetWidth, // 活动区域宽高height: node.offsetHeight,};} else {obj = {left: this.areaLeft,top: this.areaTop,width: this.areaWidth,height: this.areaHeight,};}return obj;},// 设置样式dragZoomNodeStyle() {return {transform: `scale(${this.currentZoom})`,left: `${this.initLeft}px`,top: `${this.initTop}px`,width: this.width + "px",height: this.height + "px",cursor: this.allowZoom ? "move" : "default",};},},watch: {zoom(val) {this.currentZoom = val;this.initStyle(val);},},created() {},mounted() {this.dragZoomNode.addEventListener("mousedown", this.mousedown);this.dragZoomNode.addEventListener("wheel", this.mousescroll);this.initStyle("mounted");},beforeDestroy() {this.dragZoomNode.removeEventListener("mousedown", null);this.dragZoomNode.removeEventListener("wheel", null);},methods: {// 鼠标点击事件mousedown(evt) {const areaW = this.areaNode? this.areaNode.offsetWidth: this.areaNodeData.width;const areaH = this.areaNode? this.areaNode.offsetHeight: this.areaNodeData.height;const {offsetLeft: dragL,offsetTop: dragT,offsetWidth: dragW,offsetHeight: dragH,} = this.dragZoomNode; //缩放内容的宽高与到活动区域的宽高距离const x = evt.clientX - dragL; //鼠标相对于图片的位置const y = evt.clientY - dragT;// 鼠标拖动事件document.onmousemove = (evt) => {const zoom = this.currentZoom; //缩放比// 不允许拖动if (!this.allowZoom) {return;}let styleL = evt.clientX - x;let styleT = evt.clientY - y;// 当拖动元素宽度小于父元素时if (dragW * zoom < areaW) {// 注: 使用 scale 缩放后, 元素实际尺寸不会改变const boundaryL = (dragW * zoom - dragW) / 2;const boundaryR = areaW - (dragW + boundaryL);// 左边界if (styleL < boundaryL) {styleL = boundaryL;}// 右边界if (styleL > boundaryR) {styleL = boundaryR;}} else {// 注: 使用 scale 缩放后, 元素实际尺寸不会改变const boundaryL = (dragW * zoom - dragW) / 2;const boundaryR = -(dragW * zoom - areaW - boundaryL);// 左边界if (styleL > boundaryL) {styleL = boundaryL;}// 右边界if (styleL < boundaryR) {styleL = boundaryR;}}// 当拖动元素高度小于父元素时if (dragH * zoom < areaH) {// 注: 使用 scale 缩放后, 元素实际尺寸不会改变const boundaryT = (dragH * zoom - dragH) / 2;const boundaryB = areaH - (dragH + boundaryT);// 上边界if (styleT < boundaryT) {styleT = boundaryT;}// 下边界if (styleT > boundaryB) {styleT = boundaryB;}} else {// 注: 使用 scale 缩放后, 元素实际尺寸不会改变const boundaryT = (dragH * zoom - dragH) / 2;const boundaryB = -(dragH * zoom - areaH - boundaryT);// 上边界if (styleT > boundaryT) {styleT = boundaryT;}// 下边界if (styleT < boundaryB) {styleT = boundaryB;}}this.dragZoomNode.style.left = styleL + "px";this.dragZoomNode.style.top = styleT + "px";this.lastPosition.left = styleL;this.lastPosition.top = styleT;this.$emit("mousemove", evt);};document.onmouseup = () => {document.onmousemove = null;};},// 鼠标滚轮事件mousescroll(evt) {// 阻止默认行为if (evt.preventDefault) {evt.preventDefault();} else {evt.returnValue = false;}const { deltaY } = evt;const {left: areaL,top: areaT,// width: areaW,// height: areaH,} = this.areaNodeData;const areaW = this.areaNode? this.areaNode.offsetWidth: this.areaNodeData.width;const areaH = this.areaNode? this.areaNode.offsetHeight: this.areaNodeData.height;const {offsetLeft: dragL,offsetTop: dragT,offsetWidth: dragW,offsetHeight: dragH,} = this.dragZoomNode;let zoom = this.currentZoom;// 不允许缩放if (!this.allowZoom) {return;}// 上滑if (deltaY < 0) {if (zoom >= this.maxZoom) {return;}zoom += this.range;} else {if (zoom <= this.minZoom) {return;}zoom -= this.range;}this.currentZoom = Number(zoom.toFixed(1));/* 边界判定 */const subtractW = (dragW * this.currentZoom - dragW) / 2;const subtractH = (dragH * this.currentZoom - dragH) / 2;const currentL = dragL - subtractW;const currentT = dragT - subtractW;const currentR = dragL + dragW + subtractW;const currentB = dragT + dragH + subtractH;// 当拖动元素宽度小于父元素时if (dragW * zoom < areaW) {// 左边界判定if (currentL < areaL) {this.dragZoomNode.style.left = areaL + subtractW + "px";}// 右边界判定if (currentR > areaW) {this.dragZoomNode.style.left = areaW - dragW - subtractW + "px";}} else {// 左边界判定if (currentL > areaL) {this.dragZoomNode.style.left = areaL + subtractW + "px";}// 右边界判定if (currentR < areaW) {this.dragZoomNode.style.left = areaW - dragW - subtractW + "px";}}// 当拖动元素高度小于父元素时if (dragH * zoom < areaH) {// 上边界判定if (currentT < areaT) {this.dragZoomNode.style.top = areaT + subtractH + "px";}// 下边界判定if (currentB > areaH) {this.dragZoomNode.style.top = areaH - dragH - subtractH + "px";}} else {// 上边界判定if (currentT > areaT) {this.dragZoomNode.style.top = areaT + subtractH + "px";}// 下边界判定if (currentB < areaH) {this.dragZoomNode.style.top = areaH - dragH - subtractH + "px";}}this.$emit("mousescroll", evt);},// 样式初始化initStyle(title) {let tmpLeft = this.left;let tmpTop = this.top;const { offsetWidth: dragW, offsetHeight: dragH } = this.dragZoomNode;tmpLeft = this.left - (dragW * (1 - this.zoom)) / 2;tmpTop = this.left - (dragH * (1 - this.zoom)) / 2;this.initLeft = tmpLeft || this.lastPosition.left;this.initTop = tmpTop || this.lastPosition.top;},},};</script><style scoped>.xx-drag-zoom {position: absolute;user-select: none;}</style>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。