CSS MASK 實現(xiàn)一個 Loading 效果
分享一個簡單的loading效果,如下:
本案例來源于 Temani Afif on CodePen[1],略有修改
仔細(xì)觀察,主要有兩個動畫
- 小球的運動
- 背景的變化
看似有點復(fù)雜,其實換個角度,實現(xiàn)要比想象的容易很多,也非常巧妙,一起看看吧
一、整體思路
如果按照正常的思路,可能會做兩個動畫,小球的動畫還好,只是方位的變化,但是背景就麻煩了,除了顏色的變化,還有角度的變化,該如何實現(xiàn)呢?
其實換一下角度,多觀察幾遍,將整個視野反過來,你會發(fā)現(xiàn),小球的背景相對于整個畫布是靜止的,也就是說,背景其實沒有變化,小球只是挖了一個孔,這個孔在運動,示意效果如下:
提到挖孔,可以想到遮罩(CSS Mask)。關(guān)于遮罩,這個技巧非常實用,之前在多篇文章中都有用到
- 一個有意思的CSS圖片hover效果[2]。
- CSS 如何實現(xiàn)羽化效果?[3]。
- 別用圖片了,CSS 遮罩合成實現(xiàn)帶圓角的環(huán)形 loading 動畫[4]。
- CSS mask 實現(xiàn)鼠標(biāo)跟隨鏤空效果[5]。
- CSS 實現(xiàn)Chrome標(biāo)簽欄的技巧[6]。
- CSS 實現(xiàn)優(yōu)惠券的技巧[7]。
所以,如果想到了這一點,下面的實現(xiàn)就很簡單了,一個4種顏色的背景和一個運動的黑色遮罩
二、背景的繪制
相信大家對這個背景都很熟悉,經(jīng)常在CSS繪制三角形的時候看到這個原理圖,這里同樣也可以用border來實現(xiàn)。
div{
width: 0;
border: 60px solid;
border-color: #2196F3,#F44336,#4CAF50,#FFC107
}
這樣就得到所需要的圖案。
當(dāng)然,除了這種方式,還可以采用錐形漸變來繪制。
有關(guān)錐形漸變的技巧,可以參考之前這幾篇文章
- 錐形漸變只能畫圓錐嗎?conic-gradient 10大應(yīng)用舉例[8]。
- 純CSS漸變繪制 Chrome 圖標(biāo)[9]。
- CSS & SVG 繪制寫作網(wǎng)格線的3種方式[10]。
- CSS 實現(xiàn)切角效果[11]。
- CSS 繪制一個時鐘[12]。
- CSS 實現(xiàn)透明方格的 3 種方式[13]。
實現(xiàn)也很簡單,起始角度是45deg,每 1/4換一種顏色。
div{
width: 120px;
height: 120px;
background: conic-gradient(from 45deg,#2196F3 25%,#F44336 0 50%,#4CAF50 0 75%,#FFC107 0);
}
也能得到和上面完全相同的背景。
三、鏤空小球的繪制和運動
接下來需要通過 CSS MASK來繪制小球。很簡單,就是一個從實色到透明的徑向漸變。
div{
...
-webkit-mask: radial-gradient(closest-side circle,#000 99%,#0000 100%) left/40px 40px no-repeat
}
注意,這里使用了關(guān)鍵詞closest-side,表示最近的邊,好處是可以根據(jù)背景尺寸直接控制圓的大小,默認(rèn)值是farthest-side,其他選項詳細(xì)如下:
關(guān)鍵字 | 描述 |
closest-side | 漸變中心距離容器最近的邊作為終止位置。 |
closest-corner | 漸變中心距離容器最近的角作為終止位置。 |
farthest-side | 漸變中心距離容器最遠(yuǎn)的邊作為終止位置。 |
farthest-corner(默認(rèn)值) | 漸變中心距離容器最遠(yuǎn)的角作為終止位置。 |
當(dāng)然,對于完全對稱的容器,closest-* 和 farthest-*是完全相同的,各自的區(qū)別如下所示:
可以得到這樣的效果,其余部分已經(jīng)被裁剪掉了。
最后只需要改變遮罩的位置就行了,動畫關(guān)鍵幀如下:
@keyframes load {
25% {-webkit-mask-position: top }
50% {-webkit-mask-position: right }
75% {-webkit-mask-position: bottom}
}
這樣就實現(xiàn)了文章開頭的效果:
完整代碼如下:
.loader {
width: 120px;
height: 120px;
background: conic-gradient(from 45deg,#2196F3 25%,#F44336 0 50%,#4CAF50 0 75%,#FFC107 0);
-webkit-mask: radial-gradient(50% 50%,#000 96%,#0000) left/35% 35% no-repeat;
animation: load 2s infinite;
}
@keyframes load {
25% {-webkit-mask-position: top }
50% {-webkit-mask-position: right }
75% {-webkit-mask-position: bottom}
}
完整代碼可以查看以下任意鏈接:
- CSS dot loader (juejin.cn)[14]。
- CSS dot loader (codepen.io)[15]。
- CSS dot loader (runjs.work)[16]。
四、總結(jié)一下
總的來說實現(xiàn)非常簡單,都是一些比較常規(guī)的繪制方式,但是思路卻非常巧妙,通過改變 MASK 遮罩的位置來實現(xiàn)小球的背景位置變化,下面簡單總結(jié)一下
- 整體思路其實是背景不動,挖孔在動。
- 背景可以通過不同顏色的邊框?qū)崿F(xiàn)。
- 背景還可以通過錐形漸變實現(xiàn)。
- 圓形挖孔其實就是徑向漸變的遮罩。
- 通過動畫改變遮罩的位置。
另外,關(guān)于錐形漸變和遮罩在本文介紹的并不多,但是引入了之前很多相關(guān)文章,有興趣的可以回顧一下,很多非常實用的案例。
參考資料
[1]Temani Afif on CodePen: https://codepen.io/t_afif/details/NWyOdgv。
[2]一個有意思的CSS圖片hover效果: https://juejin.cn/post/7233177170489688120。
[3]CSS 如何實現(xiàn)羽化效果?: https://juejin.cn/post/7176094306124431421。
[4]別用圖片了,CSS 遮罩合成實現(xiàn)帶圓角的環(huán)形 loading 動畫: https://juejin.cn/post/7217731969307328571。
[5]CSS mask 實現(xiàn)鼠標(biāo)跟隨鏤空效果: https://juejin.cn/post/7033188994641100831。
[6]CSS 實現(xiàn)Chrome標(biāo)簽欄的技巧: https://juejin.cn/post/6986827061461516324。
[7]CSS 實現(xiàn)優(yōu)惠券的技巧 : https://juejin.cn/post/6945023989555134494。
[8]錐形漸變只能畫圓錐嗎?conic-gradient 10大應(yīng)用舉例: https://juejin.cn/post/7212101184709247033。
[9]純CSS漸變繪制 Chrome 圖標(biāo): https://juejin.cn/post/7230603857033986109。
[10]CSS & SVG 繪制寫作網(wǎng)格線的3種方式: https://juejin.cn/post/7186524908464111676。
[11]CSS 實現(xiàn)切角效果: https://juejin.cn/post/7087774534996066334。
[12]CSS 繪制一個時鐘: https://juejin.cn/post/7090364550809124901。
[13]CSS 實現(xiàn)透明方格的 3 種方式: https://juejin.cn/post/7072175448301994020。
[14]CSS dot loader (juejin.cn): https://code.juejin.cn/pen/7235176585551167546。
[15]CSS dot loader (codepen.io): https://codepen.io/xboxyan/pen/VwEVdyR。
[16]CSS dot loader (runjs.work): https://runjs.work/projects/b90d34e7833849d6。