JavaScript實(shí)現(xiàn)電商平臺(tái)商品細(xì)節(jié)圖
本文分享一個(gè)電商平臺(tái)常見(jiàn)查看商品細(xì)節(jié)圖案例,如某東網(wǎng)站手機(jī)類(lèi)別中具體某一部手機(jī)詳情頁(yè)中,手機(jī)的細(xì)節(jié)圖展示,左側(cè)小圖獲得用戶鼠標(biāo)焦點(diǎn)即可在屏幕右側(cè)展示出該圖片區(qū)域的大圖效果,其中JS部分主要涉及鼠標(biāo)經(jīng)過(guò)、鼠標(biāo)離開(kāi)、鼠標(biāo)移動(dòng)等事件以及含有一個(gè)小算法公式,先展示效果:
某電商平臺(tái)效果圖展示:
本案例代碼部分:
HTML結(jié)構(gòu):
<div class="box"> <img src="images/s3.png" alt=""> <div class="mask"></div> <div class="big"> <img src="images/big.jpg" alt=""> </div> </div>
CSS樣式:
<style> * { padding: 0; margin: 0; } .box { position: relative; top: 70px; left: 30px; width: 400px; height: 400px; border: 1px solid #ccc; } .box > img { height: 100%; } .mask { display: none; position: absolute; top: 0; left: 0; width: 300px; height: 300px; box-sizing: border-box; background-color: rgba(254, 222, 79, .5); border: 1px solid #ccc; cursor: move; /*讓鼠標(biāo)的狀態(tài)改成十字型*/ } .big { display: none; position: absolute; top: 0; left: 410px; width: 500px; height: 500px; border: 1px solid #ccc; overflow: hidden; z-index: 999; } .big img { /* 一定要給.big下的img定位屬性它的位置才能隨著遮罩層的移動(dòng)而移動(dòng)哦 */ position: absolute; top: 0; left: 0; } </style>
JavaScript行為:
<script> window.addEventListener('load', function () { // 1.獲取元素 var box = document.querySelector('.box'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); // 2.注冊(cè)事件 // (1)box鼠標(biāo)經(jīng)過(guò)即顯示出遮罩層mask和右側(cè)大圖 onmouseover box.addEventListener('mouseover', function () { mask.style.display = 'block'; big.style.display = 'block'; }) // (2)box鼠標(biāo)離開(kāi)即隱藏遮罩層mask和右側(cè)大圖 onmouseout box.addEventListener('mouseout', function () { mask.style.display = 'none'; big.style.display = 'none'; }) // (3)讓mask遮罩層隨著鼠標(biāo)移動(dòng)(此事件要寫(xiě)在獲得鼠標(biāo)的情況下) box.addEventListener('mousemove', function (e) { // (1). 先計(jì)算出鼠標(biāo)在盒子內(nèi)的坐標(biāo),鼠標(biāo)在盒子里的坐標(biāo)=鼠標(biāo)在屏幕中的坐標(biāo)-盒子的offsetLeft/offsetTop var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // (2) 鼠標(biāo)在遮罩層中應(yīng)該處于中心的位置,所以還要把鼠標(biāo)從遮罩層的左上角往右往下移動(dòng)遮罩層寬高的一半才行,即鼠標(biāo)在盒子里的坐標(biāo)減去盒子高度的一半和寬度的一半就是我們mask 的最終 left 和top值了 var maskX = x - mask.offsetWidth / 2; // 鼠標(biāo)位置在遮罩層水平中間 var maskY = y - mask.offsetHeight / 2; // 鼠標(biāo)位置在遮罩層垂直中間 // (3) 我們mask 遮罩層水平移動(dòng)的距離即maskX= 遮罩層的父盒子的寬-遮罩層的寬,而遮罩層垂直移動(dòng)的距離即maskY= 遮罩層的父盒子的高-遮罩層的高 // (4) 如果x 坐標(biāo)小于了0 就讓他停在0 的位置 // 遮擋層的最大移動(dòng)距離= 遮罩層的父盒子的寬-遮罩層的寬(因?yàn)榇税咐恼谡謱邮且粋€(gè)正方形,所以水平和垂直的范圍是一致的) var maskMax = box.offsetWidth - mask.offsetWidth; // 遮罩層的最大移動(dòng)距離 // 判斷限定遮罩層的可移動(dòng)范圍:水平可移動(dòng)范圍: maskX <= 0 ? maskX = 0 : maskX = maskX; // 水平最小可移動(dòng)范圍 maskX >= maskMax ? maskX = maskMax : maskX = maskX; // 水平最小大可移動(dòng)范圍 // 判斷限定遮罩層的可移動(dòng)范圍:垂直可移動(dòng)范圍: maskY <= 0 ? maskY = 0 : maskY = maskY; // 垂直最小可移動(dòng)范圍 maskY >= maskMax ? maskY = maskMax : maskY = maskY; // 垂直最大可移動(dòng)范圍 // 將鼠標(biāo)的坐標(biāo)值給mask的left和top(mask是有定位的)注意要加px單位?。?! mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; // (5)讓右側(cè)大圖隨著遮罩層移動(dòng)而移動(dòng) // 大圖片的移動(dòng)距離 = 遮擋層移動(dòng)距離 * 大圖片最大移動(dòng)距離 / 遮擋層的最大移動(dòng)距離 // 獲取大圖 var bigImg = big.querySelector('img'); // 大圖片最大移動(dòng)距離 var bigMax = bigImg.offsetWidth - big.offsetWidth; // 大圖片的移動(dòng)距離 X Y var bigX = maskX * bigMax / maskMax; var bigY = maskY * bigMax / maskMax; // 注意:1.bigImg獲取到的元素需要有CSS定位屬性才能移動(dòng)位置的,沒(méi)有定位位置是不會(huì)變的哦 // 2.大圖的移動(dòng)和遮罩層移動(dòng)的方向是相反的哦,因?yàn)檎谡謱油笠苿?dòng)時(shí)實(shí)際上大圖是要往右移動(dòng)的,所以值是負(fù)數(shù) bigImg.style.left = -bigX + 'px'; bigImg.style.top = -bigY + 'px'; }) }) </script>
效果展示:
1.程序運(yùn)行,用戶鼠標(biāo)還未經(jīng)過(guò)左側(cè)小圖(.box)時(shí):
2.鼠標(biāo)經(jīng)過(guò)左側(cè)小圖時(shí) :
3.鼠標(biāo)在左側(cè)小圖(.box)上移動(dòng)時(shí):
案例知識(shí)點(diǎn)及細(xì)節(jié):
1.HTML結(jié)構(gòu)部分:主要結(jié)構(gòu)是一個(gè)大的div裝一張圖片(即左側(cè)小圖)和兩個(gè)div(一個(gè)遮罩層、一個(gè)右側(cè)裝大圖的div),這三個(gè)元素,默認(rèn)顯示的只有左側(cè)的小圖,另外的遮罩層和大圖都是默認(rèn)隱藏的(即display: none;),且遮罩層和大圖都是通過(guò)定位(子絕父相)放到對(duì)應(yīng)的位置上的,這里需要注意的是右側(cè)大圖的z-index需要給個(gè)值,因?yàn)橐话阌覀?cè)大圖原本的區(qū)域是有內(nèi)容顯示的,大圖可能會(huì)被壓在下面,所以要提一下層級(jí);
2.CSS樣式部分:樣式就根據(jù)一般樣式給就可以,唯一一點(diǎn)需要注意的是大圖里面的img要給一個(gè)position: absolute;的絕對(duì)定位,這樣JS部分才能通過(guò)left和top來(lái)移動(dòng)圖片的位置實(shí)現(xiàn)大圖隨小圖內(nèi)鼠標(biāo)的移動(dòng)而移動(dòng)的效果;
3.JavaScript部分:主要設(shè)計(jì)鼠標(biāo)經(jīng)過(guò)事件(onmouseover)、鼠標(biāo)離開(kāi)事件(onmouseout)和鼠標(biāo)移動(dòng)事件(onmousemove),注意寫(xiě)在addEventListener()內(nèi)則不需要加on,且需要用引號(hào)引起來(lái),主要思路是給最外層的大盒子(即.box)添加鼠標(biāo)經(jīng)過(guò)事件,鼠標(biāo)經(jīng)過(guò)則讓遮罩層和右側(cè)大圖顯示出來(lái)(即display: block;),鼠標(biāo)離開(kāi)則隱藏(即display: none;),然后再給.box添加鼠標(biāo)移動(dòng)事件,鼠標(biāo)在其內(nèi)部移動(dòng)先獲取到鼠標(biāo)的坐標(biāo)(用鼠標(biāo)的e.pageX - box.offsetLeft得X坐標(biāo);Y坐標(biāo)同理可得),得到鼠標(biāo)的坐標(biāo)就可以決定遮罩層的位置了,但是注意鼠標(biāo)的坐標(biāo)來(lái)決定遮罩層的位置時(shí)鼠標(biāo)應(yīng)該是在遮罩層的中心位置,所以要把得到的鼠標(biāo)坐標(biāo)往下和往右移動(dòng)遮罩層高寬的一半,這樣得到的坐標(biāo)值賦值到遮罩層上(決定的是遮罩層的左上角坐標(biāo))才對(duì);
4.遮罩層可以隨著鼠標(biāo)移動(dòng)而移動(dòng)了,但是還有一點(diǎn)那就是遮罩層的移動(dòng)范圍應(yīng)該是受限的,它不能超出父盒子,所以要添加一個(gè)判斷,如果遮罩層往左走到了0則不能再走,而往右走可以走多少其實(shí)本身是右遮罩層和其父盒子(即.box)的寬度來(lái)決定的,因?yàn)檎谡謱拥囊苿?dòng)范圍是從0~(box.offsetWidth - mask.offsetWidth),即0到父盒子的寬度減去遮罩層的寬度得來(lái)的;
5.遮罩層可以正常移動(dòng)了范圍也限制好了接下來(lái)就是右側(cè)大圖的顯示了,這里主要設(shè)計(jì)到一個(gè)算法即:
因?yàn)?strong>大圖的移動(dòng)和遮罩層的移動(dòng)其實(shí)是有比例關(guān)系的,即遮罩層移動(dòng)多少大圖按照該比例就移動(dòng)多少(比如遮罩層移動(dòng)1px,大圖移動(dòng)2px,那么遮罩層移動(dòng)2px時(shí)大圖就應(yīng)該移動(dòng)4px),由此公式可得出小圖移動(dòng)時(shí)大圖對(duì)應(yīng)應(yīng)該移動(dòng)的距離數(shù)據(jù),然后將此數(shù)據(jù)賦值給右側(cè)大圖(即div下的img),通過(guò)style.left和style.top即可改變圖標(biāo)的位置(主要值要加px單位),但是注意,大圖的移動(dòng)和遮罩層的移動(dòng)其實(shí)是相反的哦,如遮罩層往右移動(dòng),其實(shí)大圖是往左移的(因?yàn)榇髨D要往左走才能展示其右側(cè)區(qū)域),所以給left和top賦的值要加個(gè)負(fù)號(hào)哦。
如此,便基本介紹了本案例所涉及的基本知識(shí)點(diǎn)和注意點(diǎn),建議可以結(jié)合代碼(內(nèi)含詳細(xì)注釋?zhuān)┛梢愿逦目吹骄幊滩襟E以及實(shí)現(xiàn)思路。本案例是純JS底層代碼實(shí)現(xiàn)(所以具有很多可以?xún)?yōu)化的地方)或許會(huì)有更好更簡(jiǎn)單的方法實(shí)現(xiàn)此功能,但是使用最基本的JS代碼實(shí)現(xiàn)可以比較清晰的理解核心代碼和算法。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript遍歷json對(duì)象的key和任意js對(duì)象屬性實(shí)例
下面小編就為大家?guī)?lái)一篇javascript遍歷json對(duì)象的key和任意js對(duì)象屬性實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03寫(xiě)了10年的Javascript也未必全了解的連續(xù)賦值運(yùn)算
很喜歡 蔡蔡 的這個(gè)標(biāo)題,實(shí)際蔡蔡已經(jīng)分析過(guò)了,這里借用了?;蛟S有點(diǎn)標(biāo)題黨的意思??赐昃椭?。2011-03-03原生javascript實(shí)現(xiàn)圖片滾動(dòng)、延時(shí)加載功能
這篇文章主要介紹了使用原生javascript實(shí)現(xiàn)圖片滾動(dòng)、延時(shí)加載功能,思路與方法均分享給大家,希望對(duì)大家能有所幫助。2015-01-01JavaScript Event事件學(xué)習(xí)第一章 Event介紹
Events是每一個(gè)JavaScript程序核心。什么是事件處理,它有什么問(wèn)題和怎樣寫(xiě)出跨瀏覽器的代碼,我將在這一章做一個(gè)概述。我也會(huì)提供一些有精彩的關(guān)于事件處理程序的細(xì)節(jié)的文章。2010-02-02微信小程序當(dāng)前時(shí)間時(shí)段選擇器插件使用方法詳解
這篇文章主要為大家詳細(xì)介紹了微信小程序當(dāng)前時(shí)間時(shí)段選擇器插件使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12