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是通過父組件傳過來的imgList來展示的,可以換成自己的任意圖
交代一下:遮罩層和展示圖都是正方形的,而且遮罩層的寬高都是展示圖的一半
分別要綁定鼠標(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)元素是很簡單的,只需要this.$refs.mask即可。但是vue3中是沒有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)的遮罩層的圖片放大,就是簡單的乘以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(() => { // 全局事件總線,獲取兄弟組件傳遞過來的索引值 $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-03Antd-vue Table組件添加Click事件,實(shí)現(xiàn)點(diǎn)擊某行數(shù)據(jù)教程
這篇文章主要介紹了Antd-vue Table組件添加Click事件,實(shí)現(xiàn)點(diǎn)擊某行數(shù)據(jù)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11vue3-treeselect數(shù)據(jù)綁定失敗的解決方案
這篇文章主要介紹了vue3-treeselect數(shù)據(jù)綁定失敗的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05vue3簡易實(shí)現(xiàn)proxy代理實(shí)例詳解
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03vue配置electron使用electron-builder進(jìn)行打包的操作方法
這篇文章主要介紹了vue配置electron使用electron-builder進(jìn)行打包的操作方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08使用vue自定義如何實(shí)現(xiàn)Tree組件和拖拽功能
這篇文章主要介紹了使用vue自定義如何實(shí)現(xiàn)Tree組件和拖拽功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12vue.js動(dòng)態(tài)修改background-image問題
這篇文章主要介紹了vue.js動(dòng)態(tài)修改background-image問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08