在上次寫完這篇文章 -- 巧用漸變實現高階感拉滿的背景光動畫 之後,文章下面的評論有同學留言,使用 CSS 可以實現極光嗎?
像是這樣:
emmm,這有點難為人了。不過,最近我也嘗試著去試了下,雖然不可能模擬出那麼真實的效果,但是使用 CSS 還是可以作出類似的一些特效的,今天我們就一起來嘗試下。
觀察了一些極光的圖片之後,我發現了極光動畫中一些比較重要的元素:
- 基於深色背景的明亮漸變色彩
- 類似於水波流動的動畫效果
明亮漸變色彩我們可以儘量使用 漸變 模擬。而水波流動的動畫效果,在 SVG 濾鏡中 feturbulence 就是專門幹這個的,這個濾鏡的使用在我過去的多篇文章中也有反覆的提及過。
而除了漸變、SVG 的 <feturbulence>
濾鏡之外,我們可能還會用到混合模式(mix-blend-mode
)、CSS 濾鏡等提升效果。
OK,有了大概的思路後,剩下的就是不斷的嘗試。
Step 1. 繪製深色背景
首先,我們可能需要一個深色的背景,用於表示我們的夜空。同時點綴一些星星,星星可以使用 box-shadow
模擬,這樣,一副夜空背景我們可以在 1 個 div 內完成:
<div class="g-wrap">
</div>
@function randomNum($max, $min: 0, $u: 1) {
@return ($min + random($max)) * $u;
}
@function shadowSet($n, $size) {
$shadow : 0 0 0 0 #fff;
@for $i from 0 through $n {
$x: randomNum(350);
$y: randomNum(500);
$scale: randomNum($size) / 10;
$shadow: $shadow, #{$x}px #{$y}px 0 #{$scale}px rgba(255, 255, 255, .8);
}
@return $shadow;
}
.g-wrap {
position: relative;
width: 350px;
height: 500px;
background: #0b1a3a;
overflow: hidden;
&::before {
content: "";
position: absolute;
width: 1px;
height: 1px;
border-radius: 50%;
box-shadow: shadowSet(100, 6);
}
這一步比較簡單,藉助了 SASS 之後,我們能夠得到這樣一幅夜空背景圖:
Step 2. 使用漸變畫出極光的輪廓
接下來,就是利用漸變,畫出極光的一個輪廓效果。
其實就是一個徑向漸變:
<div class="g-wrap">
<div class="g-aurora"></div>
</div>
.g-aurora {
width: 400px;
height: 300px;
background: radial-gradient(
circle at 100% 100%,
transparent 45%,
#bd63c1 55%,
#53e5a6 65%,
transparent 85%
);
}
Step 3. 旋轉拉伸
目前看來,是有一點點輪廓了。下一步,我們把得到的這個漸變效果通過旋轉拉伸變換一下。
.g-aurora {
...
transform: rotate(45deg) scaleX(1.4);
}
我們大概就能得到這樣一個效果:
Step 4. 神奇的混合模式變換!
到這裡,其實雛形已經出來了。但是顏色看著不太像,為了和深色的背景融合在一起,這裡我們運用上混合模式 mix-blend-mode
。
.g-aurora {
...
transform: rotate(45deg) scaleX(1.4);
mix-blend-mode: color-dodge;
}
神奇的事情發生了,看看效果:
整體的顏色看上去更加像極光的顏色。
Step 5. 疊加 SVG feturbulence 濾鏡
接下來,我們要產生水紋波動的效果,需要藉助 SVG 的 <feturbulence>
濾鏡,對這個濾鏡還不太瞭解的,可以看看我的這幾篇文章:
迴歸正題。我們新增一個 SVG 的 <feturbulence>
濾鏡,利用 CSS filter
進行引用
<div class="g-wrap">
<div class="g-aurora"></div>
</div>
<svg id='blob' version='1.1' xmlns='http://www.w3.org/2000/svg'>
<defs>
<filter id='wave'>
<feturbulence basefrequency='0.003 0.003 id='turbulence' numoctaves='3' result='noise' seed='10' />
<fedisplacementmap id='displacement' in2='noise' in='SourceGraphic' scale='96' />
</filter>
</defs>
</svg>
.g-aurora {
...
transform: rotate(45deg) scaleX(1.4);
mix-blend-mode: color-dodge;
filter: url(#wave);
}
我們即可得到這樣一種效果:
Wow,是不是已經很有那種感覺了。通過 feturbulence 的特性,我們近乎模擬出了極光的效果!
Step 6. 讓極光動起來
最後一步,我們就需要讓我們的極光動起來。由於 SVG 動畫本身不支援類似 animation-fill-mode: alternate
這種特性。我們還是需要寫一點 JavaScript 程式碼,控制動畫的整體迴圈。
大概的程式碼是這樣:
var filter = document.querySelector("#turbulence");
var frames = 0;
var rad = Math.PI / 180;
function freqAnimation() {
bfx = 0.005;
bfy = 0.005;
frames += .5
bfx += 0.0025 * Math.cos(frames * rad);
bfy += 0.0025 * Math.sin(frames * rad);
bf = bfx.toString() + ' ' + bfy.toString();
filter.setAttributeNS(null, 'baseFrequency', bf);
window.requestAnimationFrame(freqAnimation);
}
window.requestAnimationFrame(freqAnimation);
至此,我們就得到了一幅完整的,會動的極光動畫:
一些技巧及其他事項
- 漸變元素的周圍會存在明顯的邊界毛刺效果,可以使用黑色內陰影
box-shadow: inset ...
去除; - 實際行文過程中的各個屬性的實際引數看似簡單,過程中其實經過了不斷的除錯才得到;
- 混合模式及 SVG 的 feturbulence 濾鏡比較難掌握,需要不斷的練習,不斷的除錯;本文極光的顏色選取沒有經過太多反覆除錯,願意花時間,可以除錯出效果更好的顏色。
最終的效果,不太完美,但也算一副不錯的 CSS + SVG 作品。完整的程式碼,你可以看這裡:
最後
好了,本文到此結束,希望本文對你有所幫助 ?
更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。