這篇文章主要介紹基于Vue如何實(shí)現(xiàn)商品主圖放大鏡功能,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)公司是一家專業(yè)從事做網(wǎng)站、網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司。作為專業(yè)網(wǎng)站設(shè)計(jì)公司,創(chuàng)新互聯(lián)公司依托的技術(shù)實(shí)力、以及多年的網(wǎng)站運(yùn)營(yíng)經(jīng)驗(yàn),為您提供專業(yè)的成都網(wǎng)站建設(shè)、成都全網(wǎng)營(yíng)銷推廣及網(wǎng)站設(shè)計(jì)開發(fā)服務(wù)!實(shí)現(xiàn)原理
放大鏡的原理用一句話概括,就是根據(jù)小圖上的鼠標(biāo)位置去定位大圖。
圖1 原理圖(以2倍放大為例)
相信原理圖已經(jīng)畫的很明白了, 圖中,左側(cè)框是小圖框,其藍(lán)色區(qū)域?yàn)閳D片遮罩層(需放大區(qū)域),右側(cè)框是整個(gè)大圖目前所在區(qū)域,其藍(lán)色區(qū)域是放大區(qū)域,設(shè)置超出隱藏,就實(shí)現(xiàn)了放大遮罩區(qū)域的效果。
顯然,兩塊藍(lán)色區(qū)域存在著某種對(duì)應(yīng)關(guān)系,即遮罩的左上角位置(相對(duì)于小圖,以下稱 X 坐標(biāo))和放大區(qū)域(相對(duì)于大圖)的左上角位置是成比例的,即放大倍數(shù)。計(jì)算出 X 坐標(biāo)后,適當(dāng)調(diào)整背景圖的位置,使大圖向反方向移動(dòng) scale 倍的 X 坐標(biāo)即可。
X 坐標(biāo)為(maskX,maskY),以計(jì)算 maskX 為例:
鼠標(biāo)移動(dòng)中會(huì)產(chǎn)生 e.clientX ,標(biāo)識(shí)鼠標(biāo)與瀏覽器左側(cè)的距離,小圖與瀏覽器左側(cè)的距離是 left ,由于遮罩始終是一個(gè)以鼠標(biāo)為中心的正方形,所以:
maskX = e.clientX - left - mask/2
同理,
maskY = e.clientY - top - mask/2
大圖的對(duì)應(yīng)樣式設(shè)置為:
{ left: - maskX * scale + 'px'; top: - maskY * scale + 'px'; }
效果演示
圖2 長(zhǎng)圖展示
圖3 寬圖展示
圖4 兩倍放大效果圖
圖5 四倍放大效果圖
核心代碼
HTML
一般放大鏡實(shí)現(xiàn)的是 1:1 等寬等高的正方形圖片,這里兼容了其他比例的圖片,設(shè)置圖片為垂直居中對(duì)齊,包括小圖,大圖。如果小圖不夠充滿整個(gè)小圖框,余留下的空白部分也可以有放大效果,只不過放大結(jié)果依然是空白。 這樣只需計(jì)算背景圖的移動(dòng)距離,不用過多的關(guān)注圖片定位問題。
<template> <div class="magnifier"> <!-- 小圖 --> <div class="small-box" @mouseover="handOver" @mousemove="handMove" @mouseout="handOut"> <img class="smallPic" :src="`${src}?x-oss-process=image/resize,l_836`" /> <div class="magnifier-zoom" v-show="showMask" :style="{ background: configs.maskColor, height: configs.maskWidth + 'px', width: configs.maskHeight + 'px', opacity: configs.maskOpacity, transform: transformMask }" ></div> </div> <!-- 大圖, 注意誤差 --> <div class="magnifier-layer" v-show="showMagnifier" :style="{ width: configs.width + 'px', height: configs.height + 'px', left: configs.width + 20 + 'px' }" > <div class="big-box" :style="{ width: bigWidth + 'px', height: bigHeight + 'px', left: moveLeft, top: moveTop }" > <div class="big-box-img" :style="{ width: bigWidth - 2 + 'px', height: bigHeight - 2 + 'px' }" > <img :src="bigSrc" :style="{ maxWidth: bigWidth - 2 + 'px', maxHeight: bigHeight -2 + 'px' }" /> </div> </div> </div> </div> </template>
JS
這里主要有三個(gè)事件函數(shù)。
handOver:鼠標(biāo)進(jìn)入到小圖框上的事件,此時(shí)顯示遮罩和放大區(qū)域,并計(jì)算小圖框的位置信息。
handOver() { // 計(jì)算小圖框在瀏覽器中的位置 this.imgObj = this.$el.getElementsByClassName('small-box')[0]; this.imgRectNow = this.imgObj.getBoundingClientRect(); this.showMagnifier = true; this.showMask = true; }
handMove:鼠標(biāo)在小圖上的移動(dòng)事件,此事件發(fā)生在 handOver 之后,計(jì)算數(shù)據(jù),移動(dòng)遮罩以及背景圖;
handMove(e) { // 計(jì)算初始的遮罩左上角的坐標(biāo) let objX = e.clientX - this.imgRectNow.left; let objY = e.clientY - this.imgRectNow.top; // 計(jì)算初始的遮罩左上角的坐標(biāo) let maskX = objX - this.configs.maskWidth / 2; let maskY = objY - this.configs.maskHeight / 2; // 判斷是否超出界限,并糾正 maskY = maskY < 0 ? 0 : maskY; maskX = maskX < 0 ? 0 : maskX; if(maskY + this.configs.maskHeight >= this.imgRectNow.height) { maskY = this.imgRectNow.height - this.configs.maskHeight; } if(maskX + this.configs.maskWidth >= this.imgRectNow.width) { maskX = this.imgRectNow.width - this.configs.maskWidth; } // 遮罩移動(dòng) this.transformMask = `translate(${maskX}px, ${maskY}px)`; // 背景圖移動(dòng) this.moveLeft = - maskX * this.configs.scale + "px"; this.moveTop = - maskY * this.configs.scale + "px"; }
handOut:鼠標(biāo)離開小圖事件,此時(shí)無放大鏡效果,隱藏遮罩和放大區(qū)域。
handOut() { this.showMagnifier = false; this.showMask = false; }
以上三個(gè)事件基本上就實(shí)現(xiàn)了圖片的放大鏡功能。
但仔細(xì)看,你會(huì)發(fā)現(xiàn)每次移入小圖框都會(huì)觸發(fā)一次 handOver 事件,并且計(jì)算一次小圖框 DOM (imgObj) 。
為了優(yōu)化此問題,可以用 init 標(biāo)識(shí)是否是頁(yè)面加載后首次觸發(fā) handOver 事件,如果是初始化就計(jì)算imgObj 信息,否則不計(jì)算。
handOver() { if (!this.init) { this.init = true; // 原 handOver 事件 ... } this.showMagnifier = true; this.showMask = true; },
在測(cè)試的過程中,發(fā)現(xiàn)頁(yè)面滾動(dòng)后,會(huì)出現(xiàn)遮罩定位錯(cuò)誤的情況,原來是因?yàn)槌跏蓟瘯r(shí),我們固定死了小圖框的位置信息(存放在 this.imgRectNow ),導(dǎo)致 handMove 事件中的移動(dòng)數(shù)據(jù)計(jì)算錯(cuò)誤。
解決這個(gè)問題有兩種方案:
監(jiān)聽 scroll 事件,更新 this.imgRectNow;
在 handMove 事件中更新 this.imgRectNow。
這里選擇了第二種。
handMove(e) { // 動(dòng)態(tài)獲取小圖的位置(或者監(jiān)聽 scroll ) let imgRectNow = this.imgObj.getBoundingClientRect(); let objX = e.clientX - imgRectNow.left; let objY = e.clientY - imgRectNow.top; // 原 handMove 事件剩余內(nèi)容 ... },
綜合以上,我們已經(jīng)實(shí)現(xiàn)了一個(gè)完美的圖片放大鏡功能。最終的 js 如下所示:
data() { return { imgObj: {}, moveLeft: 0, moveTop: 0, transformMask:`translate(0px, 0px)`, showMagnifier:false, showMask:false, init: false, }; }, computed: { bigWidth(){ return this.configs.scale * this.configs.width; }, bigHeight(){ return this.configs.scale * this.configs.height; } }, methods: { handMove(e) { // 動(dòng)態(tài)獲取小圖的位置(或者監(jiān)聽 scroll ) let imgRectNow = this.imgObj.getBoundingClientRect(); let objX = e.clientX - imgRectNow.left; let objY = e.clientY - imgRectNow.top; // 計(jì)算初始的遮罩左上角的坐標(biāo) let maskX = objX - this.configs.maskWidth / 2; let maskY = objY - this.configs.maskHeight / 2; // 判斷是否超出界限,并糾正 maskY = maskY < 0 ? 0 : maskY; maskX = maskX < 0 ? 0 : maskX; if(maskY + this.configs.maskHeight >= imgRectNow.height) { maskY = imgRectNow.height - this.configs.maskHeight; } if(maskX + this.configs.maskWidth >= imgRectNow.width) { maskX = imgRectNow.width - this.configs.maskWidth; } // 遮罩移動(dòng) this.transformMask = `translate(${maskX}px, ${maskY}px)`; // 背景圖移動(dòng) this.moveLeft = - maskX * this.configs.scale + "px"; this.moveTop = - maskY * this.configs.scale + "px"; }, handOut() { this.showMagnifier = false; this.showMask = false; }, handOver() { if (!this.init) { this.init = true; this.imgObj = this.$el.getElementsByClassName('small-box')[0]; } this.showMagnifier = true; this.showMask = true; } }
使用方法
本示例中的固定參數(shù):小圖框:420 * 420 。
程序可接受參數(shù):
// 小圖地址 src: { type: String, }, // 大圖地址 bigSrc: { type: String, }, // 配置項(xiàng) configs: { type: Object, default() { return { width:420,//放大區(qū)域 height:420,//放大區(qū)域 maskWidth:210,//遮罩 maskHeight:210,//遮罩 maskColor:'rgba(25,122,255,0.5)',//遮罩樣式 maskOpacity:0.6, scale:2,//放大比例 }; } }
文中圖 2 是一張長(zhǎng)圖,小圖的大邊不超過 836px(二倍圖) ,大圖為了視覺效果,分辨率盡量高點(diǎn),程序會(huì)根據(jù)配置項(xiàng)自動(dòng)設(shè)置對(duì)應(yīng)的 height , width ,長(zhǎng)圖與寬圖的效果對(duì)比可參考圖3。
配置項(xiàng)可根據(jù)應(yīng)用場(chǎng)景自行設(shè)置,本文示例的配置項(xiàng)是 2 倍放大,效果可參考圖 4,四倍放大效果可參考圖 5。
以上是“基于Vue如何實(shí)現(xiàn)商品主圖放大鏡功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
名稱欄目:基于Vue如何實(shí)現(xiàn)商品主圖放大鏡功能-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)URL:http://www.rwnh.cn/article14/igide.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、企業(yè)網(wǎng)站制作、商城網(wǎng)站、定制開發(fā)、營(yíng)銷型網(wǎng)站建設(shè)、全網(wǎng)營(yíng)銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容