Vue模仿實(shí)現(xiàn)京東商品大圖放大鏡效果
效果如下:

首先,有一個(gè)放大鏡的DOM結(jié)構(gòu)
<template>
<div class="spec-preview">
<!-- 展示的原圖 -->
<img :src="imgObj.imgUrl" />
<!-- 綁定觸發(fā) -->
<div class="event"></div>
<!-- 放大圖 -->
<div class="big">
<img :src="imgObj.imgUrl" />
</div>
<!-- 遮罩層 -->
<div class="mask"></div>
</div>
</template>這里img的src是通過(guò)父組件傳過(guò)來(lái)的imgList來(lái)展示的,可以換成自己的任意圖
交代一下:遮罩層和展示圖都是正方形的,而且遮罩層的寬高都是展示圖的一半
分別要綁定鼠標(biāo)移動(dòng)事件,和獲取兩個(gè)元素節(jié)點(diǎn),分別是遮罩層和放大圖
<template>
<div class="spec-preview">
<img :src="imgObj.imgUrl" />
<div class="event" @mousemove="handler"></div>
<div class="big">
<img :src="imgObj.imgUrl" ref="big" />
</div>
<!-- 遮罩層 -->
<div class="mask" ref="mask"></div>
</div>
</template>vue3中如何獲得ref綁定的節(jié)點(diǎn)元素呢?
首先,要知道在vue2中獲取ref節(jié)點(diǎn)元素是很簡(jiǎn)單的,只需要this.$refs.mask即可。但是vue3中是沒(méi)有this.$refs的。
<script>
import { computed, getCurrentInstance, onMounted, ref } from "vue";
export default {
name: "ZoomIndex",
props: ["skuImageList"],
setup(props) {
let mask = ref(null);
let big = ref(null);
function handler(event) {
let handlerMask = mask.value;
let handlerBig = big.value;
}
return {
handler,
mask,
big,
};
},
};
</script>為了結(jié)構(gòu)清楚,我把其他不涉及這個(gè)案例的代碼都刪掉了。handlerMask和handlerBig就是我們想要獲取的節(jié)點(diǎn)。
獲取到節(jié)點(diǎn)后,就可以寫相應(yīng)的放大器實(shí)現(xiàn)代碼了
首先要獲取event的offserX也就是我們鼠標(biāo)距離左側(cè)邊框的距離 ,然后還需要減去遮罩層本身寬度的一半,高度同理。并且添加約束條件,讓這個(gè)遮罩層不能出展示區(qū)域。最后就只需要修改相應(yīng)元素的left和top屬性即可了(當(dāng)然,這里肯定是要用到絕對(duì)定位的,子絕父相)
function handler(event) {
let handlerMask = mask.value;
let left = event.offsetX - handlerMask.offsetWidth / 2;
let top = event.offsetY - handlerMask.offsetHeight / 2;
// 約束范圍
if (left <= 0) left = 0;
if (left >= handlerMask.offsetWidth) left = handlerMask.offsetWidth;
if (top <= 0) top = 0;
if (top >= handlerMask.offsetHeight) top = handlerMask.offsetHeight;
// 修改元素的left|top屬性值
handlerMask.style.left = left + "px";
handlerMask.style.top = top + "px";
// 修改放大圖
let handlerBig = big.value;
handlerBig.style.left = -2 * left + "px";
handlerBig.style.top = -2 * top + "px";
}這里稍微有疑惑的可能就是放大圖為什么是-2去相乘。 首先根據(jù)前面的介紹,我們的展示圖和放大圖的大小是一致的,都是正方形。而遮罩層的寬高都是其一半。所以要把相應(yīng)的遮罩層的圖片放大,就是簡(jiǎn)單的乘以2即可。那為什么是負(fù)數(shù)。這就是涉及到放大圖的移動(dòng)方向了。我們遮罩層向左移動(dòng),起始放大圖是相應(yīng)的向右移動(dòng)的。

.event {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 998;
}
.mask {
width: 50%;
height: 50%;
background-color: rgba(0, 255, 0, 0.3);
position: absolute;
left: 0;
top: 0;
display: none;
}
.big {
width: 100%;
height: 100%;
position: absolute;
top: -1px;
left: 100%;
border: 1px solid #aaa;
overflow: hidden;
z-index: 998;
display: none;
background: white;
}
img {
width: 200%;
max-width: 200%;
height: 200%;
position: absolute;
left: 0;
top: 0;
}根據(jù)上面的展示(我把big里面的overflow:hidden去掉后的),可以看到,其實(shí)圖片的大小的是展示圖和放大鏡大小的2倍,超出部分是隱藏的。也就是向著相反的方向移動(dòng),使得我們遮罩層的區(qū)域放大后正好在放大鏡的展示區(qū)域中。
完整代碼如下:
<template>
<div class="spec-preview">
<img :src="imgObj.imgUrl" />
<div class="event" @mousemove="handler"></div>
<div class="big">
<img :src="imgObj.imgUrl" ref="big" />
</div>
<!-- 遮罩層 -->
<div class="mask" ref="mask"></div>
</div>
</template>
<script>
import { computed, getCurrentInstance, onMounted, ref } from "vue";
export default {
name: "ZoomIndex",
props: ["skuImageList"],
setup(props) {
const internalInstance = getCurrentInstance(); //當(dāng)前組件實(shí)例
const $bus = internalInstance.appContext.config.globalProperties.$bus;
// console.log(props);
let currentIndex = ref(0);
let mask = ref(null);
let big = ref(null);
let imgObj = computed({
get() {
return props.skuImageList[currentIndex.value] || {};
},
});
function handler(event) {
let handlerMask = mask.value;
let left = event.offsetX - handlerMask.offsetWidth / 2;
let top = event.offsetY - handlerMask.offsetHeight / 2;
// 約束范圍
if (left <= 0) left = 0;
if (left >= handlerMask.offsetWidth) left = handlerMask.offsetWidth;
if (top <= 0) top = 0;
if (top >= handlerMask.offsetHeight) top = handlerMask.offsetHeight;
// 修改元素的left|top屬性值
handlerMask.style.left = left + "px";
handlerMask.style.top = top + "px";
// 修改放大圖
let handlerBig = big.value;
handlerBig.style.left = -2 * left + "px";
handlerBig.style.top = -2 * top + "px";
}
onMounted(() => {
// 全局事件總線,獲取兄弟組件傳遞過(guò)來(lái)的索引值
$bus.on("getIndex", (index) => {
// 修改當(dāng)前響應(yīng)式數(shù)據(jù)
currentIndex.value = index.value;
});
});
return {
currentIndex,
imgObj,
handler,
mask,
big,
};
},
};
</script>
<style lang="less">
.spec-preview {
position: relative;
width: 400px;
height: 400px;
border: 1px solid #ccc;
img {
width: 100%;
height: 100%;
}
.event {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 998;
}
.mask {
width: 50%;
height: 50%;
background-color: rgba(0, 255, 0, 0.3);
position: absolute;
left: 0;
top: 0;
display: none;
}
.big {
width: 100%;
height: 100%;
position: absolute;
top: -1px;
left: 100%;
border: 1px solid #aaa;
// overflow: hidden;
z-index: 998;
display: none;
background: white;
img {
width: 200%;
max-width: 200%;
height: 200%;
position: absolute;
left: 0;
top: 0;
}
}
.event:hover ~ .mask,
.event:hover ~ .big {
display: block;
}
}
</style>到此這篇關(guān)于Vue模仿實(shí)現(xiàn)京東商品大圖放大鏡效果的文章就介紹到這了,更多相關(guān)Vue放大鏡效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于vue實(shí)現(xiàn)多引擎搜索及關(guān)鍵字提示
這篇文章主要為大家詳細(xì)介紹了基于vue實(shí)現(xiàn)多引擎搜索及關(guān)鍵字提示的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Antd-vue Table組件添加Click事件,實(shí)現(xiàn)點(diǎn)擊某行數(shù)據(jù)教程
這篇文章主要介紹了Antd-vue Table組件添加Click事件,實(shí)現(xiàn)點(diǎn)擊某行數(shù)據(jù)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
vue3-treeselect數(shù)據(jù)綁定失敗的解決方案
這篇文章主要介紹了vue3-treeselect數(shù)據(jù)綁定失敗的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
VUE登錄注冊(cè)頁(yè)面完整代碼(直接復(fù)制)
這篇文章主要給大家介紹了關(guān)于VUE登錄注冊(cè)頁(yè)面的相關(guān)資料,在Vue中可以使用組件來(lái)構(gòu)建登錄注冊(cè)頁(yè)面,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
vue3簡(jiǎn)易實(shí)現(xiàn)proxy代理實(shí)例詳解
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
vue配置electron使用electron-builder進(jìn)行打包的操作方法
這篇文章主要介紹了vue配置electron使用electron-builder進(jìn)行打包的操作方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08
使用vue自定義如何實(shí)現(xiàn)Tree組件和拖拽功能
這篇文章主要介紹了使用vue自定義如何實(shí)現(xiàn)Tree組件和拖拽功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
vue.js動(dòng)態(tài)修改background-image問(wèn)題
這篇文章主要介紹了vue.js動(dòng)態(tài)修改background-image問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08

