詳解CSS3+JS完美實現(xiàn)放大鏡模式

大概一年多之前寫過一篇文章:仿放大鏡效果的幾種方式原理解析,當時覺得自己技術可以了、飄了,于是就起了這樣牛氣哄哄的標題,其實也只算是介紹了css里的transform和animation兩種動畫方式 —— 當然,實現(xiàn)的效果也是巨簡單的那種…慚愧。
雖然后來隨著技術的增長又逐漸實現(xiàn)了canvas方式的放大鏡以及用純JS實現(xiàn)了另一種“淘寶式”的模型,但是仍然不盡人意:因為實現(xiàn)起來太復雜了,而且需依賴大部分JS邏輯,移動和顯示的效果均依賴JS,通過JS計算偏移量再渲染樣式。
但是CSS3自定義變量的出現(xiàn)讓我看到了“希望之光”!
先看效果:
其實現(xiàn)核心:
- CSS函數(shù),如:
calc()
—— 動態(tài)計算;var()
—— 使用自定義變量 - CSS偽元素:
::before/after
—— 方便控制,而且獨立于文檔流之外,易于渲染 - JS API:
offsetX/offsetY
:相對父節(jié)點區(qū)域左上角定位 - …
其實我們具體要實現(xiàn)的就是:在鼠標移入時顯示出來一個小圓圈(跟著鼠標走),這個小圓圈到哪,哪里的圖片區(qū)域就放大相應的倍數(shù)并且顯示在圓圈內(nèi)。
為什么要用offset API?
其實根據(jù)上面的描述,我們需要實時獲取鼠標的左偏移量和上偏移量,而這兩個偏移量是相對父節(jié)點的。通過左偏移量和上偏移量結合calc()
即可計算放大鏡顯示內(nèi)容相對父節(jié)點的顯示位置。
不難找到在鼠標事件對象中,js為我們提供了如下API:
screenX/screenY
:相對屏幕區(qū)域左上角定位,若發(fā)生滾動行為,則相對該區(qū)域定位pageX/pageY
:相對網(wǎng)頁區(qū)域左上角定位clientX/clientY
:相對瀏覽器可視區(qū)域左上角定位offsetX/offsetY
:相對父節(jié)點區(qū)域左上角定位,若無父節(jié)點則相對<html>
或<body>
定位
但相較而言唯一符合要求的就只有offset“相對于父元素”了。
<div class="bruce"> <div class="magnifier"></div> </div>
let magnifier=document.querySelector(".magnifier"); magnifier.addEventListener("mousemove",e=>{ //控制“鏡子”小圓圈的移動 });
放大鏡顯示內(nèi)容其實就是將原圖像放大N倍,通過上述偏移量按照比例截取一定區(qū)域顯示內(nèi)容。
先定義相關的css變量。我們設定放大倍率為2.5倍,那么被放大圖像的寬高也是原來寬高的2.5倍。聲明兩個變量,分為為 --x
和 --y
:
:root{ --ratio: 2.5; --box-w: 600px; --box-h: 400px; --outbox-w: calc(var(--box-w) * var(--ratio)); --outbox-h: calc(var(--box-h) * var(--ratio)); } .bruce{ margin-top: 50px; } .magnifier{ --x:0; --y:0; overflow: hidden; position: relative; width: var(--box-w); height: var(--box-h); background: url("img/nan.png") no-repeat center/100% 100%; cursor: grabbing; }
圖片以背景圖的形式展示,方便控制大小。
很顯然在這個場景下無需插入子節(jié)點作為放大鏡的容器了,使用::before
即可!
放大鏡在使用時寬高為100px,不使用時寬高為0。通過絕對定位布局放大鏡隨鼠標移動的位置,即聲明left和top,再通過聲明 transform:translate(-50%,-50%)
將放大鏡補位,使放大鏡中心與鼠標光標位置一致。由于聲明left和top定位放大鏡的位置,還可以聲明 will-change
改善left和top因改變而引發(fā)的性能問題!
而且用CSS解決這些問題的另一個好處就是:借助于偽元素/偽類,我們可以將一些比較細節(jié)的東西用CSS解決,而不是寄托于“繁重”的JavaScript。比如:鼠標移入樣式hover:
.magnifier::before{ --size: 0; position: absolute; left: var(--x); top: var(--y); border-radius: 100%; width: var(--size); height: var(--size); box-shadow: 1px 1px 3px rgba(0,0,0,.5); content: ""; will-change: left,top; transform: translate(-50%,-50%); } .magnifier:hover::before{ --size: 100px; }
接下來使用background實現(xiàn)(展示)放大鏡內(nèi)容。依據(jù)放大倍率為2.5倍,那么可聲明size: --outbox-w --outbox-h
,通過 position-x 和 position-y 移動背景即可,最終可連寫成 background:#333 url(背景圖片) no-repeat var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h)
。
其中 --scale-x 和 --scale-y 對應 position-x 和 position-y (即background-position
),用于隨著鼠標移動而改變背景位置。
--scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x)); --scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y));
那么上面mousemove函數(shù)中改變鏡子的“位置坐標”就可以這么寫了:
e.target.style.setProperty("--x",`${e.offsetX}px`); e.target.style.setProperty("--y",`${e.offsetY}px`);
so eazy~
最終的CSS內(nèi)容如下:
:root{ --ratio: 2.5; --box-w: 600px; --box-h: 400px; --outbox-w: calc(var(--box-w) * var(--ratio)); --outbox-h: calc(var(--box-h) * var(--ratio)); } .bruce{ margin-top: 50px; } .magnifier{ --x:0; --y:0; overflow: hidden; position: relative; width: var(--box-w); height: var(--box-h); background: url("img/nan.png") no-repeat center/100% 100%; cursor: grabbing; } .magnifier::before{ --size: 0; --scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x)); --scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y)); position: absolute; left: var(--x); top: var(--y); border-radius: 100%; width: var(--size); height: var(--size); background: #333 url("img/nan.png") no-repeat var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h); box-shadow: 1px 1px 3px rgba(0,0,0,.5); content: ""; will-change: left,top; transform: translate(-50%,-50%); } .magnifier:hover::before{ --size: 100px; }
若是::before
中想要用一張本身就是2倍大小的圖片,則background中將--outbox-w
和--outbox-h
替換為原本的--box-w
和--box-h
再做適當?shù)奈⒄{(diào)即可。
注意看你放大鏡中的內(nèi)容,它表明不只是簡單的圖片的放大,所以才有了 var(--size) / var(--ratio)
這一段代碼;
關于css中修改css3自定義變量:我仍然認為只能在“同級同屬”范圍內(nèi)才能修改并顯示成功。
到此這篇關于詳解CSS3+JS完美實現(xiàn)放大鏡模式的文章就介紹到這了,更多相關CSS3+JS放大鏡內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持腳本之家!
相關文章
- 這篇文章主要介紹了css3中仿放大鏡效果的幾種方式原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一2020-12-03
Canvas實現(xiàn)放大鏡效果完整案例分析(附代碼)
這篇文章主要介紹了Canvas實現(xiàn)放大鏡效果完整案例分析(附代碼),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編2020-11-26- 這篇文章主要介紹了HTML5 Canvas實現(xiàn)放大鏡效果示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習2020-03-25
- 這篇文章主要介紹了canvas離屏技術與放大鏡實現(xiàn)代碼示例的相關資料,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-31
- KeyMob移動端廣告平臺為應用開發(fā)者和廣告主提供應用交叉推廣、手機廣告優(yōu)化等一站式移動營銷解決方案,使應用開發(fā)者和廣告主獲得價值的最大化2016-01-07
- 一款用純css3實現(xiàn)的圖片放大鏡特效。頁面打開五個小圖顯示于頁面。當鼠標經(jīng)過圖片時,當前圖片以灰色背景圖的形式展示,需要的朋友不要錯過2014-09-02
CSS實現(xiàn)圓形放大鏡狙擊鏡效果 只有圓圈里的放大
圖片放大,這是一個比較容易的效果了。當然,今天說的可不是簡簡單單的在一個框里放大,而是一個圓,就像放大鏡或是狙擊鏡那樣,只有圓圈里的放大,圈外的當然還是原來的圖2012-12-10