手把手教會你用Javascript實(shí)現(xiàn)放大鏡效果(詳細(xì)注釋+完整代碼)
今天來實(shí)現(xiàn)一個(gè)類似于淘寶京東商品店鋪首頁的放大鏡效果?。?!
具體實(shí)現(xiàn)效果如下圖所示
案例分析
1.要實(shí)現(xiàn)放大鏡效果,我們需要做哪些準(zhǔn)備工作?
答:
我們首先需要?jiǎng)?chuàng)建三個(gè)盒子,分別對應(yīng)的是小圖片,大圖片,遮罩層
2.頁面創(chuàng)建完畢,如何開始操作呢?
答:
第一步:我們需要先獲取鼠標(biāo)的坐標(biāo),遮罩層的坐標(biāo)
第二步:判斷遮罩層是否超出小盒子的范圍,超出則拉回
第三步:計(jì)算大圖跟隨遮罩層移動(dòng)的比例
第四步:最關(guān)鍵的一步,就是必須在頁面加載完畢后進(jìn)行計(jì)算小圖片/遮罩層的比例=大圖片/大盒子的比例
思路拆解
首先,我們需要準(zhǔn)備兩張大小不等的相同圖片,同時(shí)搭建基本html框架,引入圖片
<body> <div id="div-small"> <img src="./imgs/小1.jpg" id="img-small"> <div id="div-mask"></div> </div> <div id="div-big"> <img src="./imgs/大2.jpg" id="img-big"> </div> </body>
搭建完成后,還看不出效果,所以我們還需要加入css樣式進(jìn)行頁面渲染
<style> img { vertical-align: top; } /*小盒子*/ #div-small { width: 350px; height: 350px; outline: 2px solid black; position: absolute; top: 50px; left: 0; /*鼠標(biāo)變成小手樣式*/ cursor: pointer; } /*大盒子*/ #div-big { width: 500px; height: 500px; outline: 2px solid black; position: absolute; left: 350px; top: 50px; overflow: hidden; display: none; } /*遮罩層*/ #div-mask { width: 150px; height: 150px; background-color: aqua; opacity: 0.5; position: absolute; top: 0; left: 0; /*對鼠標(biāo)事件失去作用*/ pointer-events: none; display: none; } </style>
為了更好的展示圖片效果,在遮罩層和大盒子被隱藏前,截了一張圖如下;畢竟為了更好的實(shí)現(xiàn)放大鏡效果,遮罩層和大盒子都是需要提前隱藏的
通過上面的步驟,基本實(shí)現(xiàn)頁面的基本效果,接下來就需要加入JavaScript實(shí)現(xiàn)頁面的交互效果。鼠標(biāo)移入小盒子,顯示遮罩層和大盒子,鼠標(biāo)移出,遮罩層和大盒子隱藏.
//鼠標(biāo)移入事件 div_small.onmouseover = function () { //鼠標(biāo)移入小盒子時(shí),遮罩層和大盒子顯示 div_mask.style["display"] = "block"; div_big.style["display"] = "block"; } //鼠標(biāo)移出事件 div_small.onmouseout = function () { //鼠標(biāo)移出小盒子時(shí),遮罩層和大盒子消失 div_mask.style["display"] = "none"; div_big.style["display"] = "none"; //同時(shí)讓大盒子圖片回到原位 img_big.style["margin-left"] = 0; img_big.style["margin-top"] = 0; }
有了上面的移出和移入事件后,就需要實(shí)現(xiàn)左邊遮罩層移動(dòng),右邊大盒子圖片進(jìn)行對應(yīng)放大處理
//(小盒子內(nèi))鼠標(biāo)移動(dòng)事件 div_small.onmousemove = function (e) { //通過1和2可以確保鼠標(biāo)在遮罩層的正中間 //1.獲取鼠標(biāo)在小盒子的位置x0,y0 let x0 = e.offsetX; let y0 = e.offsetY; //2.計(jì)算當(dāng)前位置(左上角) let cur_x = x0 - div_mask.offsetWidth / 2; let cur_y = y0 - div_mask.offsetHeight / 2; //2-1.防止遮罩越界(超出盒子區(qū)域),超出則拉回 cur_x = cur_x < 0 ? 0 : cur_x; cur_x = cur_x > div_small.offsetWidth - div_mask.offsetWidth ? div_small.offsetWidth - div_mask.offsetWidth : cur_x; cur_y = cur_y < 0 ? 0 : cur_y; cur_y = cur_y > div_small.offsetHeight - div_mask.offsetHeight ? div_small.offsetHeight - div_mask.offsetHeight : cur_y; //3.設(shè)置遮罩的(左上角)位置 div_mask.style["left"] = cur_x + "px"; div_mask.style["top"] = cur_y + "px"; //4.讓大圖挪動(dòng)(大圖移動(dòng)距離等于小圖距離左邊的寬高乘以大小圖的寬高比) img_big.style["margin-left"] = -cur_x * img_big.offsetWidth / img_small.offsetWidth + "px"; img_big.style["margin-top"] = -cur_y * img_big.offsetHeight / img_small.offsetHeight + "px"; }
完成上面的思路后,基本上就完成了一個(gè)簡易版的放大鏡,但會存在一個(gè)小問題,就是右邊的圖片和左邊遮罩層移動(dòng)的比例似乎不一致,存在些許誤差。
所以,就需要進(jìn)行關(guān)鍵一步的處理,讓放大鏡更完美;即利用動(dòng)態(tài)等比縮放的方式,使左右兩邊圖片比例一致
//圖片會在頁面內(nèi)容加載完畢后才會開始加載,所以使用window.onload. window.onload = function () { //計(jì)算小圖片/遮罩層的比例=大圖片/大盒子的比例===>即動(dòng)態(tài)設(shè)置大圖片的寬高,讓大圖片始終貼合邊框(注意:元素設(shè)置display:none后,offsetWidth這種獲取寬高將會失效) img_big.style.width = (img_small.offsetWidth / parseFloat((window.getComputedStyle(div_mask)["width"])) * parseFloat((window.getComputedStyle(div_big)["width"]))) + "px"; img_big.style.height = (img_small.offsetHeight / parseFloat((window.getComputedStyle(div_mask)["height"])) * parseFloat((window.getComputedStyle(div_big)["height"]))) + "px"; }
以上就是實(shí)現(xiàn)放大鏡效果的全部思路,希望能幫到你!!!
完整代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> img { vertical-align: top; } /*小盒子*/ #div-small { width: 350px; height: 350px; outline: 2px solid black; position: absolute; top: 50px; left: 0; /*鼠標(biāo)變成小手樣式*/ cursor: pointer; } /*大盒子*/ #div-big { width: 500px; height: 500px; outline: 2px solid black; position: absolute; left: 350px; top: 50px; overflow: hidden; display: none; } /*遮罩層*/ #div-mask { width: 150px; height: 150px; background-color: aqua; opacity: 0.5; position: absolute; top: 0; left: 0; /*對鼠標(biāo)事件失去作用*/ pointer-events: none; display: none; } </style> </head> <body> <div id="div-small"> <img src="./imgs/小1.jpg" id="img-small"> <div id="div-mask"></div> </div> <div id="div-big"> <img src="./imgs/大2.jpg" id="img-big"> </div> </body> <script> //獲取標(biāo)簽 let div_small = document.querySelector("#div-small"); let div_big = document.querySelector("#div-big"); let div_mask = document.querySelector("#div-mask"); let img_small = document.querySelector("#img-small"); let img_big = document.querySelector("#img-big"); //假定鼠標(biāo)控制遮罩層在當(dāng)前盒子的正中間,我們需要先求出遮罩層左上角的坐標(biāo)(x=e.offsetX-mask.offsetWidth,y=e.offsetY-mask.offsetHeight) //鼠標(biāo)移入事件 div_small.onmouseover = function () { //鼠標(biāo)移入小盒子時(shí),遮罩層和大盒子顯示 div_mask.style["display"] = "block"; div_big.style["display"] = "block"; } //鼠標(biāo)移出事件 div_small.onmouseout = function () { //鼠標(biāo)移出小盒子時(shí),遮罩層和大盒子消失 div_mask.style["display"] = "none"; div_big.style["display"] = "none"; //同時(shí)讓大盒子圖片回到原位 img_big.style["margin-left"] = 0; img_big.style["margin-top"] = 0; } //(小盒子內(nèi))鼠標(biāo)移動(dòng)事件 div_small.onmousemove = function (e) { //通過1和2可以確保鼠標(biāo)在遮罩層的正中間 //1.獲取鼠標(biāo)在小盒子的位置x0,y0 let x0 = e.offsetX; let y0 = e.offsetY; //2.計(jì)算當(dāng)前位置(左上角) let cur_x = x0 - div_mask.offsetWidth / 2; let cur_y = y0 - div_mask.offsetHeight / 2; //2-1.防止遮罩越界(超出盒子區(qū)域),超出則拉回 cur_x = cur_x < 0 ? 0 : cur_x; cur_x = cur_x > div_small.offsetWidth - div_mask.offsetWidth ? div_small.offsetWidth - div_mask.offsetWidth : cur_x; cur_y = cur_y < 0 ? 0 : cur_y; cur_y = cur_y > div_small.offsetHeight - div_mask.offsetHeight ? div_small.offsetHeight - div_mask.offsetHeight : cur_y; //3.設(shè)置遮罩的(左上角)位置 div_mask.style["left"] = cur_x + "px"; div_mask.style["top"] = cur_y + "px"; //4.讓大圖挪動(dòng)(大圖移動(dòng)距離等于小圖距離左邊的寬高乘以大小圖的寬高比) img_big.style["margin-left"] = -cur_x * img_big.offsetWidth / img_small.offsetWidth + "px"; img_big.style["margin-top"] = -cur_y * img_big.offsetHeight / img_small.offsetHeight + "px"; } //圖片會在js加載完畢后才會開始加載,所以使用window.onload. window.onload = function () { //計(jì)算小圖片/遮罩層的比例=大圖片/大盒子的比例===>即動(dòng)態(tài)設(shè)置大圖片的寬高,讓大圖片始終貼合邊框(注意:元素設(shè)置display:none后,offsetWidth這種獲取寬高將會失效) img_big.style.width = (img_small.offsetWidth / parseFloat((window.getComputedStyle(div_mask)["width"])) * parseFloat((window.getComputedStyle(div_big)["width"]))) + "px"; img_big.style.height = (img_small.offsetHeight / parseFloat((window.getComputedStyle(div_mask)["height"])) * parseFloat((window.getComputedStyle(div_big)["height"]))) + "px"; } </script> </html>
總結(jié)
到此這篇關(guān)于Javascript實(shí)現(xiàn)放大鏡效果的文章就介紹到這了,更多相關(guān)js放大鏡效果內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript強(qiáng)制點(diǎn)擊廣告的方法
這篇文章主要介紹了javascript強(qiáng)制點(diǎn)擊廣告的方法,可用于下載站或文檔顯示站,實(shí)現(xiàn)點(diǎn)擊后才能出現(xiàn)相應(yīng)顯示的功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-02-02js實(shí)現(xiàn)橫向百葉窗效果網(wǎng)頁切換動(dòng)畫效果的方法
這篇文章主要介紹了js實(shí)現(xiàn)橫向百葉窗效果網(wǎng)頁切換動(dòng)畫效果的方法,實(shí)例分析了javascript實(shí)現(xiàn)百葉窗效果的技巧,需要的朋友可以參考下2015-03-03javascript根據(jù)時(shí)間生成m位隨機(jī)數(shù)最大13位
javascript根據(jù)時(shí)間生成m位隨機(jī)數(shù),最大13位隨機(jī)數(shù),并且不能保證首位不為0,實(shí)現(xiàn)代碼如下,需要的朋友可以參考下2014-10-10JQuery入門——用one()方法綁定事件處理函數(shù)(僅觸發(fā)一次)
one()方法功能是為所選的元素綁定一個(gè)僅觸發(fā)一次的處理函數(shù),感興趣的朋友可以了解下它的調(diào)用語法為:one(type, [data], fn),閱讀本文或許有意外的收獲呢2013-02-02使用JS判斷是否數(shù)字和小數(shù)點(diǎn)組合的數(shù)字的兩中方法比較(isNaN和逐判斷)
使用js判斷數(shù)字和小數(shù)點(diǎn)的方法非常之多。但是就目前而言,我見過最好用的判斷方法應(yīng)該來說是isNaN,它比較方便,而逐個(gè)比較的方法有一定的弊端。2009-09-09