前段时间写了一个类似于百度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.https://www.npmjs.com/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>

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

  1. swift 拖动按钮_Swift下使用UICollectionView 实现长按拖拽功能

    导读 简单用Swift写了一个collectionview的拖拽点击排序效果; 拖拽排序是新闻类的App可以说是必有的交互设计,如今日头条,网易新闻等. 效果 主要代码 手势长按移动 1.给Colle ...

  2. 【项目技术点总结之一】vue集成d3.js利用svg加载图片实现缩放拖拽功能

    [项目技术点总结之一]vue集成d3.js利用svg加载图片实现缩放拖拽功能 前言 概述 技术介绍 实现过程 插件安装 引用组件 初始化组件 实现效果 简单理解 使用d3创建一个svg 在svg中提添 ...

  3. ae可围绕帧拖动放大插件:Drag Zoom Pro for AE mac(兼容M1)

    Drag Zoom Pro for AE是一个可围绕帧创建矩形并拖动旋转放大矩形内画面的插件,创建具有自然运动模糊的平滑过渡以放大帧的各个部分,而无需在"变换"效果中手动调整&qu ...

  4. vue 悬浮按钮_Vue@哇!几行代码实现拖拽视图组件

    概述 最近开发的项目中有一个分享的悬浮按钮,这个按钮遮挡了页面信息,产品经理跑过来问我,是否可以把这个按钮做成可以拖拽的,研究了一下轻松实现了这个功能,这里分享给大家.这个项目是基于vue的公众号网页 ...

  5. [vue] 怎么捕获组件vue的错误信息?

    [vue] 怎么捕获组件vue的错误信息? errorHandler 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

  6. vue项目中图标可拖拽功能实现

    vue项目中页面实现图标拖拽功能 最近在做项目需求时有个小功能:在页面的首页增加一个快速功能按钮,用来满足操作者快速实现某一目的渴望.为了体现代码搬运工的气质与水准,当时心想,这么简单的一个小东西必须 ...

  7. 【vue弹框和div拖拽功能】vue-elementul弹框拖拽功能,移动拖拽功能,普通div拖拽功能【拿来即用,直接复制】

    前言 这里是通过vue的指令封装好的 直接创建一个js文件复制进去,引入一下就搞定了,非常简单 html版本引入vue语法的div和弹框拖拽功能 这里是考虑到有时候会在html页面开发的时候也会用到这 ...

  8. 拖拽功能 php,基于Vue实现拖拽功能

    这篇文章主要为大家详细介绍了Vue实现拖拽功能,拖动方块进行移动,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了Vue实现拖拽功能的具体代码,供大家参考,具体内容如下 效果图: ...

  9. vuedraggable能实现自由拖拽功能吗?_基于 vue.js 仿禅道主页拖拽效果

    今天给大家分享一个超不错的Vue仿禅道首页拖拽布局VueDndKon. vue-dnd-kon 基于vuedraggable实现的仿禅道首页拖拽项目.支持模块上下及左右自由拖动布局. 主页分为左右两栏 ...

  10. vue:实现简单的拖拽功能

    背景 平常做业务很容易遇到拖拽功能,没做之前总觉得会很复杂,今天来看一下到底是怎么实现的. 拖拽API 这是 HTML5 新增的 API,当给元素设置 draggable="true&quo ...

最新文章

  1. c语言函数参数类型检查,内联函数在编译时是否做参数类型检查?
  2. jdk1.7 hashmap多线程下的死循环
  3. NOIP2012开车旅行 【倍增】
  4. 打分排序系统漫谈1 - 时间衰减
  5. jquery ajax json table 添加行,使用jQuery从AJAX响应构建表行(json)
  6. android activityManager
  7. Spring boot学习整理
  8. linux nohup后台执行管道操作
  9. logic:equal,logic:present用法
  10. 《Effective Python 2nd》——元类与属性
  11. Loadrunner 11检查点使用方法总结
  12. 传智播客java课程表,先睹为快
  13. 黑苹果intel网卡驱动
  14. 如何修改SAO用户密码
  15. laravel 自定义分页样式
  16. 每日一Tip:Jetbrains旗下集成环境(pycharm、IDEA等)使用Ctrl +鼠标滚轮上下滑放大缩小快捷键设置
  17. python进阶之路———文件处理
  18. 程序员追求技术夯实基础学习路线建议
  19. android--手机震动--Vibrator
  20. 管道和FIFO概念以及相关函数(pipe、mkfifo)介绍

热门文章

  1. u盘在电脑上读不出来?数据恢复解决方法在这
  2. 简单的MD5查询工具
  3. 网管疑惑:当一个网银助手需要管理员权限才肯运行时,咋整?
  4. 在PC上安装WM5中文版模拟器
  5. Followme外汇社区隐私政策
  6. 【Follow me】总结
  7. 小米air13.3win10安装Ubuntu18.04双系统
  8. eDonkey协议规范
  9. 审美--《艺术与审美》课程学习笔记
  10. 基于Android个人日常消费理财_财务软件app