本文是基于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.deg}deg)`;
},
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浏览器判断滚轮滚动的方向是属性 wheelDelta
const 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.deg}deg)`;
},
页面销毁的时候 注意要取消鼠标的监听事件
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.deg}deg)`;
},
/**
* 图片的缩放
* 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.deg}deg)`;
},
/**
* 重置
*/
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>
最后附上完整的项目代码 代码仓库地址