canvas中的拖拽、缩放、旋转(手机查看)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canvas中的拖拽、缩放、旋转(手机查看)相关的知识,希望对你有一定的参考价值。

参考技术A <html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<meta charset="utf-8"/>
<title>canvas中的拖拽,缩放,旋转</title>
<style type="text/css">
.canvas-container
border: 1px solid #aaa;
width: 302px;
margin: 0 auto;


</head>
<body>
<div class="canvas-container">
<canvas width='300' height="300"></canvas>
</div>
<div class="box-container">
<div class="red-box"></div>
</div>
</body>
</html>

<script type="text/javascript">
const BOX_PADDING = 10;
const ICON_HEIGHT = 20;
const ROTATE_ICON = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA70lEQVQ4T7XTL0vDURTG8c80aJVhEWx2u2AyTYNonmAwGi2Cgth8AWNBgzYZLKmwMJhYLL4Io9hFDP7hyJ2My+/nlLHTzj3P/d5znntvxYhRGXG/sQGWsI1nfGIGD7hI+U/jRR0c4QmneE/KSRxgFruDY+eAFSwjIEVxgkc0+8UccIcaXkoAE7hJmm/JIKCKM2wMuZku1vCWA6bQwvoQQAer+MgBkfdS8TWDzGMTDVyVjRB7trCIvQwQa3VMo43bMhPDk2MsYD85HtoAXOMch79dY78WRsaJc9hJD+oS8R4iAn5f5MG/v8bY/sKfO/kCL2skEWR80iIAAAAASUVORK5CYII=';
const DEL_ICON = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABIUlEQVRYR+3VPUvEQBSF4WdLsRdBQQsrURErC/31CtoJfiDICooigr22cnEDYdGdO5tgmqQJITNz3jn3zpmJgZ/JwPpGgNGB0YGsAzt4w2fy2K5iHY+l8RmAXdzhFad4Kiy6jTNsYh+3i8ZnAFZwjXChBNEWn+IAX10BYn7YeYmtBRBt8Wcc472PEjRrhKXnf0DMi5/MQEv61VH8G0SINDWPnafFY2KmB+Z30YYIwXiiNNXiywLEvIC4mL3jeynxrgBNP/w7wKAlyDRh6vg1jVXThNljGAEUiVnMgJoeqA2iNETGgdoojtMRwA847COK93CTuAeassadEcEUEHGR3fdxFxzhBR/FbP0ZsIYNXJXGZ0pQWqPT/xFgdGB0YHAHvgG1jEwhcd+TtgAAAABJRU5ErkJggg==';
const SCALE_ICON = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABJElEQVRYR+3UPS8EURTG8d82GolE0NArlT6ARqEiChrRKXTUWqUtJSpCQoNKlEqlL6CloJB4aVRyky2QnZk7szOzzb3NFPPkPP/z3HNux5BPZ8j+EkBKICVQJYExnCF8s84D9vFatOZVAXYKCq9iGvN4zNNWAShqaglXeMItttsEWMY5NrGASawMCjCOb3wVtB7ML7CGaxzVBXCKF+zmAPw3D9LaAEI3AWArA6CfeWsAWeatAOSZNw4QBu0Y672B63c7jc1AMD/prddNzmB2MYGNQdfw9xDGmgfPUYzgrS6Au8jOi17KP/9jnuJDLGImIvZS5kEcAzCLezzjssDhAO9lKGIAQr0p7GEup/hnbys+mgAoU7OUNjaBUkXLiBNASiAl8AO7pD8h3UM4owAAAABJRU5ErkJggg==';

</script>

Vue2 实现图片的拖拽缩放旋转

本文是基于vue2 实现图片的拖拽、旋转、鼠标滚动放大缩小等功能。

效果图

分步骤实现

在这里看下 拖拽、旋转、缩放的几个方法

1.获取图片的实际宽高

getImgSize(url) return new Promise((resolve, reject) => let imgObj = new Image();imgObj.src = url;imgObj.onload = () => resolve(width: imgObj.width,height: imgObj.height,);;);
, 

2.根据盒子的大小、图片的大小来计算 要显示多大的图片

 async initImage() if (!this.imageUrl) return;let  width, height  = await this.getImgSize(this.imageUrl);// 设置原始图片的大小let realWidth = width;let realHeight = height;// 获取高宽比例const whRatio = realWidth / realHeight;const hwRatio = realHeight / realWidth;//获取盒子的大小const boxW = this.$refs.maskBox.clientWidth;const boxH = this.$refs.maskBox.clientHeight;if (realWidth >= realHeight) this.imgH = hwRatio * boxW;const nih = this.imgH;if (nih > boxH) this.imgH = boxH;this.imgW = whRatio * boxH; else this.imgW = boxW;this.top = (boxH - this.imgH) / 2;this.left = (boxW - this.imgW) / 2; else this.imgW = (boxH / realHeight) * realWidth;this.imgH = boxH;this.left = (boxW - this.imgW) / 2;, 

在这里主要是根据图片的宽高 ,以及盒子的大小来计算 盒子中展示多大的图片,将图片按照比例缩放后展示到盒子中。

3.拖拽图片

主要是监听@mousedown事件

onmousedownHandle(e) const that = this;this.$refs.maskBox.onmousemove = function (el) const ev = el || window.event; // 阻止默认事件ev.preventDefault();that.left += ev.movementX;that.top += ev.movementY;;this.$refs.maskBox.onmouseup = function () // 鼠标抬起时将操作区域的鼠标按下和抬起事件置为null 并初始化that.$refs.maskBox.onmousemove = null;that.$refs.maskBox.onmouseup = null;;if (e.preventDefault) e.preventDefault(); else return false;
, 

4. 旋转图片

handleRotate() this.deg += 90;if (this.deg >= 360) this.deg = 0;this.size = 0;this.scale = `scale(1) rotateZ($this.degdeg)`;
, 

5.监听鼠标的滚动,进行缩放图片

在 mounted() 中监听鼠标的滚动事件

mounted() // 兼容火狐浏览器this.mousewheelevt = /Firefox/i.test(navigator.userAgent)? "DOMMouseScroll" : "mousewheel";// 为空间区域绑定鼠标滚轮事件 =》 处理函数是wheelHandle// 如果你监听了window的scroll或者touchmove事件,你应该把passive设置为true,这样滚动就会流畅很多this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle, passive:true);
, 

处理鼠标的滚动事件

wheelHandle(e) // 兼容性处理 => 火狐浏览器判断滚轮的方向是属性 detail,谷歌和ie浏览器判断滚轮滚动的方向是属性 wheelDeltaconst ev = e || window.event;// dir = -dir; // dir > 0 => 表示的滚轮是向上滚动,否则是向下滚动 => 范围 (-120 ~ 120)const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;//滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例this.imgScaleHandle(dir / 2000);
, 

放大缩小图片

/**
 * 图片的缩放
 * zoom >0 放大
 * zoom <0 缩小
 */
imgScaleHandle(zoom) this.size += zoom;if (this.size < -0.5) this.size = -0.5;this.scale = `scale($1 + this.size) rotateZ($this.degdeg)`;
, 

页面销毁的时候 注意要取消鼠标的监听事件

beforeDestroy() //取消监听this.$refs.maskBox.removeEventListener(this.mousewheelevt,this.wheelHandle,passive:true);
, 

以上就是主要实现功能的方法

完整代码

<template><div class="home"><div class="btn-area"><button @click="switchImgHandle(1)">竖图</button><button @click="switchImgHandle(2)">横图</button><button @click="handleRotate">旋转</button><button @click="imgScaleHandle(0.25)">放大</button><button @click="imgScaleHandle(-0.25)">缩小</button><button @click="handleReset">重置</button></div><div class="image-box" ref="maskBox" @mousedown="onmousedownHandle"><img :src="imageUrl" alt="" :style="width: imgW + 'px', height: imgH + 'px',top: top + 'px', left: left + 'px', transform: scale, " /></div></div>
</template>

<script>
export default name: "HomeView",data() return imageUrl: "",imageUrl1: require("@/assets/img1.jpg"),imageUrl2: require("@/assets/img2.jpg"),imgW: 0,imgW: 0,imgH: 0,deg: 0,top: 0,left: 0,scale: "scale(1)",size: 0,mousewheelevt: null,;,mounted() this.imageUrl = this.imageUrl1;//初始化图片this.initImage();// 兼容火狐浏览器this.mousewheelevt = /Firefox/i.test(navigator.userAgent) ? "DOMMouseScroll" :"mousewheel";// 为空间区域绑定鼠标滚轮事件 =》 处理函数是wheelHandle// 如果你监听了window的scroll或者touchmove事件,你应该把passive设置为true,这样滚动就会流畅很多this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle,  passive:true);,beforeDestroy() //取消监听this.$refs.maskBox.removeEventListener(this.mousewheelevt,this.wheelHandle,passive:true);,methods: /** * 切换图片 *flag: 1竖图 2 横图 */switchImgHandle(flag) if (flag === 1) this.imageUrl = this.imageUrl1; else this.imageUrl = this.imageUrl2;this.handleReset();,/** * 获取图片的url * @param string url */getImgSize(url) return new Promise((resolve, reject) => let imgObj = new Image();imgObj.src = url;imgObj.onload = () => resolve(width: imgObj.width,height: imgObj.height,);;);,/** * 初始化图片 */async initImage() if (!this.imageUrl) return;let  width, height  = await this.getImgSize(this.imageUrl);// 设置原始图片的大小let realWidth = width;let realHeight = height;// 获取高宽比例const whRatio = realWidth / realHeight;const hwRatio = realHeight / realWidth;//获取盒子的大小const boxW = this.$refs.maskBox.clientWidth;const boxH = this.$refs.maskBox.clientHeight;if (realWidth >= realHeight) this.imgH = hwRatio * boxW;const nih = this.imgH;if (nih > boxH) this.imgH = boxH;this.imgW = whRatio * boxH; else this.imgW = boxW;this.top = (boxH - this.imgH) / 2;this.left = (boxW - this.imgW) / 2; else this.imgW = (boxH / realHeight) * realWidth;this.imgH = boxH;this.left = (boxW - this.imgW) / 2;,/** * 旋转 */handleRotate() this.deg += 90;if (this.deg >= 360) this.deg = 0;this.size = 0;this.scale = `scale(1) rotateZ($this.degdeg)`;,/** * 图片的缩放 *zoom >0 放大 *zoom <0 缩小 */imgScaleHandle(zoom) this.size += zoom;if (this.size < -0.5) this.size = -0.5;this.scale = `scale($1 + this.size) rotateZ($this.degdeg)`;,/** * 重置 */handleReset() this.imgW = 0;this.imgH = 0;this.top = 0;this.left = 0;this.deg = 0;this.scale = "scale(1)";this.size = 0;this.initImage();,/** * 鼠标滚动 实现放大缩小 */wheelHandle(e) const ev = e || window.event; // 兼容性处理 => 火狐浏览器判断滚轮的方向是属性 detail,谷歌和ie浏览器判断滚轮滚动的方向是属性 wheelDelta// dir = -dir; // dir > 0 => 表示的滚轮是向上滚动,否则是向下滚动 => 范围 (-120 ~ 120)const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;//滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例this.imgScaleHandle(dir / 2000);,/** * 处理图片拖动 */onmousedownHandle(e) const that = this;this.$refs.maskBox.onmousemove = function (el) const ev = el || window.event; // 阻止默认事件ev.preventDefault();that.left += ev.movementX;that.top += ev.movementY;;this.$refs.maskBox.onmouseup = function () // 鼠标抬起时将操作区域的鼠标按下和抬起事件置为null 并初始化that.$refs.maskBox.onmousemove = null;that.$refs.maskBox.onmouseup = null;;if (e.preventDefault) e.preventDefault(); else return false;,,
;
</script>

<style scoped>
.home width: 1000px;margin: 50px auto;

.btn-area display: flex;justify-content: center;width: 100%;margin-bottom: 50px;

.btn-area button width: 100px;height: 40px;font-size: 18px;margin-right: 10px;

.image-box position: relative;margin: 0 auto;width: 1000px;height: 700px;border: 1px solid #333;overflow: hidden;

.image-box img position: absolute;cursor: pointer;

</style> 

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

以上是关于canvas中的拖拽、缩放、旋转(手机查看)的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序的拖拽缩放和旋转手势

Vue2 实现图片的拖拽缩放旋转

如何实现Canvas图像的拖拽,点击等操作

canvasn拖拽效果

简单实现svg的拖拽和缩放

在vue中使用alloyfinger,实现元素的拖拽,缩放,双击,长按等功能