Vue2實(shí)現(xiàn)圖片的拖拽,縮放和旋轉(zhuǎn)效果的示例代碼
效果圖

分步驟實(shí)現(xiàn)
在這里看下 拖拽、旋轉(zhuǎn)、縮放的幾個(gè)方法
1.獲取圖片的實(shí)際寬高
getImgSize(url) {
return new Promise((resolve, reject) => {
let imgObj = new Image();
imgObj.src = url;
imgObj.onload = () => {
resolve({
width: imgObj.width,
height: imgObj.height,
});
};
});
},2.根據(jù)盒子的大小、圖片的大小來(lái)計(jì)算 要顯示多大的圖片
async initImage() {
if (!this.imageUrl) {
return;
}
let { width, height } = await this.getImgSize(this.imageUrl);
// 設(shè)置原始圖片的大小
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;
}
},在這里主要是根據(jù)圖片的寬高 ,以及盒子的大小來(lái)計(jì)算 盒子中展示多大的圖片,將圖片按照比例縮放后展示到盒子中。
3.拖拽圖片
主要是監(jiān)聽@mousedown事件
onmousedownHandle(e) {
const that = this;
this.$refs.maskBox.onmousemove = function (el) {
const ev = el || window.event; // 阻止默認(rèn)事件
ev.preventDefault();
that.left += ev.movementX;
that.top += ev.movementY;
};
this.$refs.maskBox.onmouseup = function () {
// 鼠標(biāo)抬起時(shí)將操作區(qū)域的鼠標(biāo)按下和抬起事件置為null 并初始化
that.$refs.maskBox.onmousemove = null;
that.$refs.maskBox.onmouseup = null;
};
if (e.preventDefault) {
e.preventDefault();
} else {
return false;
}
},4. 旋轉(zhuǎn)圖片
handleRotate() {
this.deg += 90;
if (this.deg >= 360) {
this.deg = 0;
}
this.size = 0;
this.scale = `scale(1) rotateZ(${this.deg}deg)`;
},5.監(jiān)聽鼠標(biāo)的滾動(dòng),進(jìn)行縮放圖片
在 mounted() 中監(jiān)聽鼠標(biāo)的滾動(dòng)事件
mounted() {
// 兼容火狐瀏覽器
this.mousewheelevt = /Firefox/i.test(navigator.userAgent)? "DOMMouseScroll" : "mousewheel";
// 為空間區(qū)域綁定鼠標(biāo)滾輪事件 =》 處理函數(shù)是wheelHandle
// 如果你監(jiān)聽了window的scroll或者touchmove事件,你應(yīng)該把passive設(shè)置為true,這樣滾動(dòng)就會(huì)流暢很多
this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle, {passive:true});
},處理鼠標(biāo)的滾動(dòng)事件
wheelHandle(e) {
// 兼容性處理 => 火狐瀏覽器判斷滾輪的方向是屬性 detail,谷歌和ie瀏覽器判斷滾輪滾動(dòng)的方向是屬性 wheelDelta
const ev = e || window.event;
// dir = -dir; // dir > 0 => 表示的滾輪是向上滾動(dòng),否則是向下滾動(dòng) => 范圍 (-120 ~ 120)
const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;
//滾動(dòng)的數(shù)值 / 2000 => 表示滾動(dòng)的比例,用此比例作為圖片縮放的比例
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)`;
},頁(yè)面銷毀的時(shí)候 注意要取消鼠標(biāo)的監(jiān)聽事件
beforeDestroy() {
//取消監(jiān)聽
this.$refs.maskBox.removeEventListener(this.mousewheelevt,this.wheelHandle,{passive:true});
},以上就是主要實(shí)現(xiàn)功能的方法
完整代碼
<template>
<div class="home">
<div class="btn-area">
<button @click="switchImgHandle(1)">豎圖</button>
<button @click="switchImgHandle(2)">橫圖</button>
<button @click="handleRotate">旋轉(zhuǎn)</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";
// 為空間區(qū)域綁定鼠標(biāo)滾輪事件 =》 處理函數(shù)是wheelHandle
// 如果你監(jiān)聽了window的scroll或者touchmove事件,你應(yīng)該把passive設(shè)置為true,這樣滾動(dòng)就會(huì)流暢很多
this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle, { passive:true});
},
beforeDestroy() {
//取消監(jiān)聽
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);
// 設(shè)置原始圖片的大小
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;
}
},
/**
* 旋轉(zhuǎn)
*/
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();
},
/**
* 鼠標(biāo)滾動(dòng) 實(shí)現(xiàn)放大縮小
*/
wheelHandle(e) {
const ev = e || window.event; // 兼容性處理 => 火狐瀏覽器判斷滾輪的方向是屬性 detail,谷歌和ie瀏覽器判斷滾輪滾動(dòng)的方向是屬性 wheelDelta
// dir = -dir; // dir > 0 => 表示的滾輪是向上滾動(dòng),否則是向下滾動(dòng) => 范圍 (-120 ~ 120)
const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;
//滾動(dòng)的數(shù)值 / 2000 => 表示滾動(dòng)的比例,用此比例作為圖片縮放的比例
this.imgScaleHandle(dir / 2000);
},
/**
* 處理圖片拖動(dòng)
*/
onmousedownHandle(e) {
const that = this;
this.$refs.maskBox.onmousemove = function (el) {
const ev = el || window.event; // 阻止默認(rèn)事件
ev.preventDefault();
that.left += ev.movementX;
that.top += ev.movementY;
};
this.$refs.maskBox.onmouseup = function () {
// 鼠標(biāo)抬起時(shí)將操作區(qū)域的鼠標(biāo)按下和抬起事件置為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>
以上就是Vue2實(shí)現(xiàn)圖片的拖拽,縮放和旋轉(zhuǎn)效果的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue圖片拖拽 縮放 旋轉(zhuǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
elementui實(shí)現(xiàn)標(biāo)簽頁(yè)與菜單欄聯(lián)動(dòng)的示例代碼
多級(jí)聯(lián)動(dòng)是一種常見的交互方式,本文主要介紹了elementui實(shí)現(xiàn)標(biāo)簽頁(yè)與菜單欄聯(lián)動(dòng)的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06
vue?頂部消息橫向滾動(dòng)通知效果實(shí)現(xiàn)
系統(tǒng)頂部展示一個(gè)橫向滾動(dòng)的消息通知,就是消息內(nèi)容從右往左一直滾動(dòng),這篇文章主要介紹了vue頂部消息橫向滾動(dòng)通知,需要的朋友可以參考下2024-02-02
vue2.0中click點(diǎn)擊當(dāng)前l(fā)i實(shí)現(xiàn)動(dòng)態(tài)切換class
本篇文章主要介紹了vue2.0中click點(diǎn)擊當(dāng)前l(fā)i實(shí)現(xiàn)動(dòng)態(tài)切換class ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
Vue使用new?Blob()實(shí)現(xiàn)不同類型的文件下載功能
這篇文章主要給大家介紹了關(guān)于Vue使用new?Blob()實(shí)現(xiàn)不同類型的文件下載功能的相關(guān)資料,在Vue項(xiàng)目中,經(jīng)常用Blob二進(jìn)制進(jìn)行文件下載功能,需要的朋友可以參考下2023-07-07
Vue2+marked.js實(shí)現(xiàn)AI流式輸出的項(xiàng)目實(shí)踐
本文主要介紹了Vue2+marked.js實(shí)現(xiàn)AI流式輸出的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
基于Vue2x實(shí)現(xiàn)響應(yīng)式自適應(yīng)輪播組件插件VueSliderShow功能
本文講述的是從開發(fā)一款基于Vue2x的響應(yīng)式自適應(yīng)輪播組件插件的一個(gè)全過(guò)程,包含發(fā)布到npm,構(gòu)建自己的npm包,供下載安裝使用的技巧,非常不錯(cuò),具有一定的參考借鑒價(jià)值,感興趣的朋友跟隨腳本之家小編一起看看吧2018-05-05
Vue Promise解決回調(diào)地獄問(wèn)題實(shí)現(xiàn)方法
這篇文章主要介紹了Vue Promise解決回調(diào)地獄問(wèn)題,總的來(lái)說(shuō)這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達(dá)的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過(guò)程。希望通過(guò)這道題能給你帶來(lái)一種解題優(yōu)化的思路2023-01-01

