基于JavaScript實現(xiàn)圖片放大鏡功能
在一些電商網站上,經??吹接猩唐穲D片被放大查看的功能,包括另外一些圖片展示站點,也有類似的功能。
如果我們想讓圖片能展示更多細節(jié)清晰的內容,實現(xiàn)這樣一個放大鏡功能,是非常劃算的,既能使用小圖顯示滿足大多數用戶的查看需求,又能通過放大圖片的方式顯示更清晰內容。這樣,一方面可以節(jié)省不必要的大圖流量,又能滿足對圖片清晰度有要求的用戶需求。
所以,本文將使用前端技術實現(xiàn)一個簡單的圖片放大鏡功能,希望能給大家?guī)硪欢ǖ膸椭?/p>
圖片放大鏡效果
我們可以先來看下圖片放大鏡最后的效果圖:
如上圖所示,
左邊的小圖方塊內,就是需要放大的圖片,上面有一個蒙層區(qū)域(可視作放大鏡),只可以在小圖范圍內移動,該蒙層遮住的區(qū)域就代表圖片需要放大的部分;
右邊的大圖方塊內,展示的是蒙層部分放大后的清晰圖像,這里本質上是顯示的完整像素的圖片、或者是比左邊更大像素的高清圖片。
左邊蒙層的實時移動,在右邊顯示清晰圖像,這就形成了一個圖片放大鏡的功能效果。
接下來,我們具體看看它的實現(xiàn)過程。
實現(xiàn)過程
一、設計UI界面
要實現(xiàn)放大鏡功能,就要先設計好界面布局,從上面的效果圖里看到,界面上分了兩塊:一個是原始的縮略小圖區(qū)域;一個是放大后的預覽大圖區(qū)域。
在html中使用div來布局的話,如下所示:
<div id="el_EnlargeContainer" class="enlarge"> <!--左邊原始小圖區(qū)域--> <div id="el_SmallContainer" class="small"> <img id="el_SmallImage"/> <div id="el_maskEnarge" class="mask"></div> </div> <!--右邊預覽大圖區(qū)域--> <div id="el_PreviewContainer" class="preview"> <img id="el_PreviewImage"/> </div> </div>
從以上html代碼可知,
外層定義了一個 el_EnlargeContainer
的整個放大功能整體內容區(qū)域,里面有兩個子元素:一個是縮略小圖的div,包含一個img圖片元素用于展示縮略圖,還有一個蒙層的div元素;另外一個是預覽大圖區(qū)域,包含有放大后的大圖img元素,這里加載的是原始大尺寸圖。
主要樣式設置
蒙層需要覆蓋在縮略小圖的上面,所以需要使用絕對定位方式,并且設置帶透明度的顏色,鼠標樣式也設置為 move
,默認隱藏,具體的CSS樣式如下所示:
.mask { position: absolute; top: 0; left: 0; background: rgba(255, 255, 0, 0.6); cursor: move; display: none; }
預覽大圖區(qū)域樣式類 preview
,由于要顯示在右側區(qū)域,也可以使用絕對定位的方式,超出顯示在小圖區(qū)域的右邊即可:
.preview { position: absolute; top: 0; left: 150px; /* ... */ }
其他的樣式設置都較簡單,根據布局方式一一展示即可,這里就先略過。
下面,我們需要做的是加載圖片。
二、加載縮略小圖
上面的代碼中,我們只定義了img標簽元素,并沒有直接加載圖片資源,這是由于我們做的是以動態(tài)加載圖片的方式來實現(xiàn)這個放大鏡功能。
當動態(tài)加載圖片資源后,需要根據圖片像素寬高,設置對應界面元素的大小和位置信息。
縮略小圖作為首先需要主體展示的資源,我們需要先加載,并設置小圖區(qū)域容器和圖片的大小:
el_SmallImage.onload = () => { let { width, height } = el_SmallImage const smallScale = Math.min(SMALLSIZE / width, SMALLSIZE / height, 1) smallImgWidth = width * smallScale smallImgHeight = height * smallScale el_EnlargeContainer.style.width = el_SmallImage.style.width = smallImgWidth + 'px' el_EnlargeContainer.style.height = el_SmallImage.style.height = smallImgHeight + 'px' resolve(el_SmallImage) } el_SmallImage.src = imgSrc
以上代碼,加載縮略小圖后,獲取到圖片的寬高數據,然后相應的計算。其中 SMALLSIZE
是預先定義的一個常量,表示小圖區(qū)域的一個固定尺寸大小,可根據需要自定義取值,通過該值計算縮略圖的縮放比例——縮略圖依據該固定尺寸,計算合適的寬高比例進行展示。
注意,這里設置的是整個放大鏡的整體內容區(qū)域 el_EnlargeContainer
的大小,就是小圖展示的大小,而預覽放大的圖片是浮在右側的,并不被包含在這塊區(qū)域內。
這時候的縮略圖,就是我們網站要穩(wěn)定展示的圖片信息,作為用戶初始瀏覽的內容,如下圖:
一般電商網站上,使用輪播圖切換的方式,展示縮略圖片信息。
從上圖可見,只展示了縮略圖片,放大后的預覽大圖還沒涉及到,是因為我們可以在監(jiān)聽事件里進行加載,有利于節(jié)省圖片加載流量。
三、縮略圖事件監(jiān)聽
接下來,我們需要處理縮略小圖的事件監(jiān)聽,實現(xiàn)加載預覽大圖、蒙層移動的效果。
根據上面的html布局,我們在縮略小圖的外部容器 el_SmallContainer
上添加鼠標事件,主要是 onmouseenter
、onmouseleave
、onmousemove
三個事件。
onmouseenter
事件,當鼠標進入到頁面展示的縮略圖上時進行處理,這時需要做兩件事:一是加載預覽大圖的原始圖像,二是顯示蒙層和預覽大圖的完整內容區(qū)域。
el_SmallContainer.onmouseenter = async () => { // 加載預覽大圖原始圖 if (loadPreviewImage === null) { loadPreviewImage = await setPreviewImage(previewImgUrl) } // 顯示蒙層和預覽大圖區(qū)域 el_maskEnarge.style.display = 'block' el_PreviewContainer.style.display = 'block' }
以上代碼,就是鼠標進入事件的處理,其中有加載并設置預覽大圖的原始數據信息,具體代碼如下所示:
let { width, height } = el_PreviewImage let previewScale = Math.min(PREVIEWSIZE / width, PREVIEWSIZE / height, 1) el_PreviewContainer.style.width = width * previewScale + 'px' el_PreviewContainer.style.height = height * previewScale + 'px' el_PreviewContainer.style.left = (smallImgWidth + 10) + 'px' el_maskEnarge.style.width = smallImgWidth * previewScale + 'px' el_maskEnarge.style.height = smallImgHeight * previewScale + 'px'
以上代碼,用于加載預覽大圖,這時能獲取到圖片的原始寬高數據,其中 PREVIEWSIZE
也是預先定義的常量,表示預覽大圖區(qū)域的一個固定尺寸大小。大圖寬高與PREVIEWSIZE尺寸計算出對應的縮放比,用于計算實際展示區(qū)域的尺寸。
而 el_PreviewContainer
預覽大圖容器內容需要定位在右側區(qū)域,設置 left
樣式屬性。
另外,蒙層的大小也得設置,蒙層大小是在縮略小圖區(qū)域展示的,但要使用預覽大圖的縮放比,這樣才能得到準確的蒙層內容用于在右側放大區(qū)域呈現(xiàn)放大效果。
onmouseleave
事件比較簡單,當鼠標離開縮略圖內容區(qū)域的時候,就隱藏蒙層和預覽大圖區(qū)域,放大鏡效果隱藏:
el_SmallContainer.onmouseleave = () => { el_maskEnarge.style.display = 'none' el_PreviewContainer.style.display = 'none' }
定義了放大鏡的顯示和隱藏事件后,就應該處理移動的效果了,移動實現(xiàn)實時放大,使用到 onmousemove
鼠標事件。
四、實現(xiàn)放大
鼠標移動也是在縮略小圖內容區(qū)域,對 el_SmallContainer
元素進行事件監(jiān)聽:
el_SmallContainer.onmousemove = (event) => { // ... }
在該事件中,我們需要處理以下幾件事:
獲取鼠標移動的位置信息
let x = event.pageX - el_EnlargeContainer.offsetLeft - el_maskEnarge.offsetWidth / 2 let y = event.pageY - el_EnlargeContainer.offsetTop - el_maskEnarge.offsetHeight / 2
以上代碼里,讀取了蒙層的offset數據,是為了移動時,能夠讓鼠標顯示在蒙層的中心位置。
限制蒙層移動的范圍,不能超出縮略小圖內容區(qū)域
const xMax = el_SmallContainer.offsetWidth - el_maskEnarge.offsetWidth x = x < 0 ? 0 : (x > xMax ? xMax : x) const yMax = el_SmallContainer.offsetHeight - el_maskEnarge.offsetHeight y = y < 0 ? 0 : (y > yMax ? yMax : y)
更新蒙層的位置信息,實時移動蒙層元素
el_maskEnarge.style.left = x + 'px' el_maskEnarge.style.top = y + 'px'
設置預覽大圖顯示的位置信息
const rate = el_PreviewImage.offsetWidth / el_SmallContainer.offsetWidth el_PreviewImage.style.marginTop = -(rate * y) + 'px' el_PreviewImage.style.marginLeft = -(rate * x) + 'px'
以上代碼,是在一定的內容區(qū)域里,加載一張完整原始尺寸的大圖,但多余的部分先隱藏 overflow: hidden;
。然后計算縮略小圖和預覽大圖的比值,右側的預覽大圖等比例移動,通過使用 marginTop
和 marginLeft
屬性設置定位的方式來移動。注意,這里處理的 el_PreviewImage
原始大圖元素。 數據取負值,是相對于初始加載時候左上角的值。
總結
至此,一個可以非固定尺寸、動態(tài)加載圖片的放大鏡功能就基本完成了。
動態(tài)加載圖片,可以不用考慮圖片的像素寬高,任意尺寸的圖片都可以完整放大,縮略小圖和預覽大圖也可以是同一張圖片。
另外,就是放大鏡的內容顯示區(qū)域,是根據不同圖片的比例進行動態(tài)計算的,尺寸大小可變,但能夠通過常量設定,控制在一定范圍內。
圖片放大鏡功能的大部分代碼都已在文章中列出來了,根據這些內容,還可以適當修改,更改成各種符合我們需求的插件。
固定尺寸
很多網站在處理放大鏡功能上,使用的是固定尺寸縮略小圖和預覽大圖的方式。
我們當然也可以處理固定尺寸,這個時候就需要特定尺寸的縮略小圖和原始大圖,直接設置元素的固定尺寸,縮略圖也可以直接加載:
/* 放大鏡區(qū)域的大小 */ .enlarge { /* ... */ width: 150px; height: 150px; } /* 縮略小圖的大小 */ .small img { width: 150px; height: 150px; } /* 蒙層大小 */ .mask { /* ... */ width: 75px; height: 75px; } /* 預覽大圖區(qū)域的大小 */ .preview { /* ... */ width: 300px; height: 300px; }
<img id="el_SmallImage" src="chrome.png"/>
以上代碼,通過css直接設置各區(qū)域的寬高大小,縮略圖也是直接加載,如此處理,就不需要手動設定各元素的寬高。
同樣可以在鼠標進入事件中加載原始大圖,這個時候圖片尺寸也是固定的。
其他事件處理,基本相同,這樣就可以增加一個固定圖像尺寸和固定界面尺寸的放大鏡功能了。
到此這篇關于基于JavaScript實現(xiàn)圖片放大鏡功能的文章就介紹到這了,更多相關JavaScript圖片放大鏡內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
uniapp實現(xiàn)tabBar-switchTab之間的傳參方法
這篇文章主要介紹了uniapp實現(xiàn)tabBar-switchTab之間的傳參方式,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-01-01javascript實現(xiàn)劃詞標記劃詞搜索功能修正版
javascript實現(xiàn)劃詞標記劃詞搜索功能修正版...2006-12-12JavaScript知識點總結(六)之JavaScript判斷變量數據類型
這篇文章主要介紹了JavaScript知識點總結(六)之JavaScript判斷變量數據類型的相關資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-05-05js中Object.defineProperty()方法的不詳解
這篇文章主要介紹了js中Object.defineProperty()方法的不詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07