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

Posted Web_boom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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道面试题,并对每个问题作出了回答和解析。

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

部分文档展示:



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

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

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

在开发中,有时会遇到像App中的手势那样的效果,下面就仿照App实现了一下。

wxml部分:


&lt;view class="touch-container"&gt;
 &lt;view class="msg"&gt;{{msg}}&lt;/view&gt;
 &lt;image
 class="img"
 src="{{src}}"
 style="width: {{width}}rpx; height: {{height}}rpx; left: {{left}}rpx; top: {{top}}rpx; transform: translate(-50%, -50%) scale({{ scale }}) rotate({{ rotate }}deg);"
 bindload="bindload"
 catchtouchstart="touchstart"
 catchtouchmove="touchmove"
 catchtouchend="touchend"
 &gt;&lt;/image&gt;
&lt;/view&gt;

wxss:


page {
  width: 100%;
  height: 100%;
  background: #ffffff;
}
.touch-container {
  width: 100%;
  height: 100%;
  padding-top: 0.1px;
}
.msg {
  width: 100%;
  height: 60rpx;
  line-height: 60rpx;
  text-align: center;
  font-size: 30rpx;
  color: #666666;
}
.img {
  position: absolute;
  width: 690rpx;
  height: 300rpx;
  transform-origin: center center;
}

js部分:




var canOnePointMove = false
var onePoint = {
  x: 0,
  y: 0
}
var twoPoint = {
  x1: 0,
  y1: 0,
  x2: 0,
  y2: 0
}
Page({
  data: {
    msg: '',
    src: 'http://img01.taopic.com/150508/318763-15050PU9398.jpg',
    width: 0,
    height: 0,
    left: 375,
    top: 600,
    scale: 1,
    rotate: 0
 },
 // 关闭上拉加载
  onReachBottom: function() {
 return
 },
  bindload: function(e) {
 var that = this
 var width = e.detail.width
 var height = e.detail.height
 if (width &gt; 750) {
      height = 750 * height / width
      width = 750
 }
 if (height &gt; 1200) {
      width = 1200 * width / height
      height = 1200
 }
    that.setData({
      width: width,
      height: height
 })
 },
  touchstart: function(e) {
 var that = this
 if (e.touches.length &lt; 2) {
      canOnePointMove = true
      onePoint.x = e.touches[0].pageX * 2
      onePoint.y = e.touches[0].pageY * 2
 }else {
      twoPoint.x1 = e.touches[0].pageX * 2
      twoPoint.y1 = e.touches[0].pageY * 2
      twoPoint.x2 = e.touches[1].pageX * 2
      twoPoint.y2 = e.touches[1].pageY * 2
 }
 },
  touchmove: function(e){
 var that = this
 if (e.touches.length &lt; 2 &amp;&amp; canOnePointMove) {
 var onePointDiffX = e.touches[0].pageX * 2 - onePoint.x
 var onePointDiffY = e.touches[0].pageY * 2 - onePoint.y
      that.setData({
        msg: '单点移动',
        left: that.data.left + onePointDiffX,
        top: that.data.top + onePointDiffY
 })
      onePoint.x = e.touches[0].pageX * 2
      onePoint.y = e.touches[0].pageY * 2
 }else if (e.touches.length &gt; 1) {
 var preTwoPoint = JSON.parse(JSON.stringify(twoPoint))
      twoPoint.x1 = e.touches[0].pageX * 2
      twoPoint.y1 = e.touches[0].pageY * 2
      twoPoint.x2 = e.touches[1].pageX * 2
      twoPoint.y2 = e.touches[1].pageY * 2
 // 计算角度,旋转(优先)
 var perAngle = Math.atan((preTwoPoint.y1 - preTwoPoint.y2)/(preTwoPoint.x1 - preTwoPoint.x2))*180/Math.PI
 var curAngle = Math.atan((twoPoint.y1 - twoPoint.y2)/(twoPoint.x1 - twoPoint.x2))*180/Math.PI
 if (Math.abs(perAngle - curAngle) &gt; 1) {
        that.setData({
          msg: '旋转',
          rotate: that.data.rotate + (curAngle - perAngle)
 })
 }else {
 // 计算距离,缩放
 var preDistance = Math.sqrt(Math.pow((preTwoPoint.x1 - preTwoPoint.x2), 2) + Math.pow((preTwoPoint.y1 - preTwoPoint.y2), 2))
 var curDistance = Math.sqrt(Math.pow((twoPoint.x1 - twoPoint.x2), 2) + Math.pow((twoPoint.y1 - twoPoint.y2), 2))
        that.setData({
          msg: '缩放',
          scale: that.data.scale + (curDistance - preDistance) * 0.005
 })
 }
 }
 },
  touchend: function(e) {
 var that = this
    canOnePointMove = false
 }
})

json部分:


"navigationBarTitleText": "识别手势",
 "navigationBarTextStyle":"black",
 "navigationBarBackgroundColor": "#FFF",
 "disableScroll": true

以上是关于Vue2 实现图片的拖拽缩放旋转的主要内容,如果未能解决你的问题,请参考以下文章

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

图片的拖拽,缩放,截图功能--自写版

js实现图片滚轮、按钮缩放大小,图片旋转,图片拖拽

简单实现svg的拖拽和缩放

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

touch 的图片缩放 拖拽