詳解CSS3+JS完美實(shí)現(xiàn)放大鏡模式
大概一年多之前寫過(guò)一篇文章:仿放大鏡效果的幾種方式原理解析,當(dāng)時(shí)覺(jué)得自己技術(shù)可以了、飄了,于是就起了這樣牛氣哄哄的標(biāo)題,其實(shí)也只算是介紹了css里的transform和animation兩種動(dòng)畫方式 —— 當(dāng)然,實(shí)現(xiàn)的效果也是巨簡(jiǎn)單的那種…慚愧。
雖然后來(lái)隨著技術(shù)的增長(zhǎng)又逐漸實(shí)現(xiàn)了canvas方式的放大鏡以及用純JS實(shí)現(xiàn)了另一種“淘寶式”的模型,但是仍然不盡人意:因?yàn)閷?shí)現(xiàn)起來(lái)太復(fù)雜了,而且需依賴大部分JS邏輯,移動(dòng)和顯示的效果均依賴JS,通過(guò)JS計(jì)算偏移量再渲染樣式。
但是CSS3自定義變量的出現(xiàn)讓我看到了“希望之光”!
先看效果:

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



