新聞中心
最近我在 CodePen 上看到了這樣一個有意思的動畫:

整個動畫效果是在一個標簽內(nèi),借助了 SVG PATH 實現(xiàn)。其核心在于對漸變(Gradient)的究極利用。
完整的代碼你可以看看這里 -- CodePen DEMO -- to the future By Jane Ori[1]]。
源代碼還是非常非常復雜的,并且疊加了復雜的 SVG PATH 路徑。
我嘗試著將其稍微拆分成幾小塊,運用不同的 CSS 高階技巧從另外一個方面方向重新實現(xiàn)了一遍。因為整個過程還是有非常多有意思的 CSS 技巧,本文就給大家分享一下。
實現(xiàn)上半部分背景加落日
首先,我們來實現(xiàn)上半部分的背景加落日效果:
大家可以先停頓思考下,這里讓你來實現(xiàn),會如何去做?需要多少個標簽?
好的,這里,我們利用一個 DOM 標簽去完成這個圖形:
背景色好做,使用一個徑向漸變或者線性漸變即可:
.g-bg {
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
}如此,先實現(xiàn)一個背景:
好,接下來,我們使用其中一個偽元素實現(xiàn)落日的效果。
.g-bg {
position: absolute;
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
&::before {
content: "";
position: absolute;
bottom: 20%;
left: 10%;
right: 10%;
top: 10%;
background: radial-gradient(circle at 50% 100%, var(--color3), var(--color4) 55%, transparent 55.1%, transparent);
}
}效果如下:
到這里,我覺得算是出現(xiàn)了第一個技巧,也就是這一行代碼 background: radial-gradient(circle at 50% 100%, var(--color3), var(--color4) 55%, transparent 55.1%, transparent),它用于在一個矩形元素中,通過徑向漸變從實色到透明色,實現(xiàn)一個半圓。
技巧 1:可以利用徑向漸變,在一個矩形 DIV 元素中,通過徑向漸變從實色到透明色的變化,實現(xiàn)一個半圓。
我們繼續(xù),接下來,切割這個圓形,得到這樣一種效果:
注意,這里需要裁剪切割的地方不是白色,而是透明的,需要透出后面的背景色。
毫無疑問,這里需要使用 mask 來完成,我們給偽元素加上 mask:
.g-bg {
position: absolute;
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
&::before {
content: "";
position: absolute;
bottom: 20%;
left: 10%;
right: 10%;
top: 10%;
background: radial-gradient(circle at 50% 100%, var(--color3), var(--color4) 55%, transparent 55.1%, transparent);
mask: linear-gradient(to top,
#000 0, #000 10%,
transparent 10%, transparent 13%,
#000 13%, #000 20%,
transparent 20%, transparent 22%,
#000 22%, #000 35%,
transparent 35%, transparent 36%,
#000 36%, #000 100%);
}
}這樣,我們就實現(xiàn)了這個效果:
這里,引出了第二個技巧:
技巧 2:利用 mask 可以對圖形進行裁剪,被裁剪區(qū)域?qū)兂赏该鳌?/p>
好,接下來,我們需要在整個圖形上再疊加上豎形黑色條紋。這個其實也可以用 mask,如果整個圖形后面還有一層黑色背景。
當然,這里我們也可以把另外一個偽元素利用起來,利用它,通過多重線性漸變(repeating-linear-gradient)實現(xiàn)這里的豎形黑色條紋。
看看代碼:
.g-bg {
position: absolute;
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
&::before {
content: "";
// code of sun
}
&::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
background: repeating-linear-gradient(90deg, transparent 0, transparent 3px, rgba(0,0,0,.5) 4px, rgba(0,0,0,.5) 5px);
}
}這里,我們利用 repeating-linear-gradient 快速創(chuàng)建批量的豎形黑色條紋效果,得到這樣的效果:
這里,得到技巧 3。
技巧 3:當你碰到大量重復有規(guī)律的線條,或者方塊圖形,你第一時間就應該想到在一個 DOM 中利用漸變而不是多個 DOM 去實現(xiàn)
好,至此,我們整個上半部分就實現(xiàn)了。
利用 -webkit-box-reflect 實現(xiàn)倒影
有了上面的基礎,接下來我們要得到完整的背景:
怎么做呢?換個配色重新實現(xiàn)一遍嗎?當然不是,這里我們利用 CSS 提供的倒影功能,可以快速完成這個操作。
.g-bg {
position: absolute;
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
-webkit-box-reflect: below;
&::before {
content: "";
// ...
}
&::after {
content: "";
// ...
}
}我們給 .g-bg 加一個 -webkit-box-reflect: below,意為下方的倒影:
雖然是復制了一個一模一樣的 .g-bg 出來,但是和我們要的效果還相差很多啊,怎么辦呢?
別急,-webkit-box-reflect: below 還提供,倒影偏移距離,倒影遮罩等屬性。
我們需要給下方的倒影,添加一個遮罩,修改一下 -webkit-box-reflect 的代碼:
.g-bg {
position: absolute;
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
-webkit-box-reflect: below -50px linear-gradient(rgba(255, 255, 255, .2), transparent);
&::before {
content: "";
// ...
}
&::after {
content: "";
// ...
}
}這樣,我們就得到了這樣一種效果:
這里,整個圖形其實是半透明的,我們在背后疊加上一層我們想要的色彩漸變,可以利用 body 的偽元素:
body {
&::before {
position: absolute;
content: "";
top: 50%;
left: 0;
bottom: 0;
right: 0;
background: linear-gradient(var(--c5), var(--c6));
}
}
.g-bg {
position: absolute;
background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
-webkit-box-reflect: below -50px linear-gradient(rgba(255, 255, 255, .2), transparent);
&::before {
content: "";
// ...
}
&::after {
content: "";
// ...
}
}倒影通過半透明和背后的漸變背景疊加,這樣,我們就完美實現(xiàn)了我們想要的整體背景效果:
這里,我們可以引出技巧 4。
技巧 4:當出現(xiàn)重復的對稱圖形時,-webkit-box-reflect 也許能派上用場。
利用 CSS 3D 動畫實現(xiàn)線條動畫
好,主體背景完成了,下面,我們來試著實現(xiàn) 3D 線條動畫:
利用 CSS 3D,我們是可以實現(xiàn)這樣一種效果的。我們一步一步來拆解。
首先,我們需要實現(xiàn)這樣一種網(wǎng)格效果:
還記得上面的技巧 3 嗎?當你碰到大量重復有規(guī)律的線條,或者方塊圖形,你第一時間就應該想到在一個 DOM 中利用漸變而不是多個 DOM 去實現(xiàn)。
這種效果,其實利用漸變一個標簽就組足夠了:
.grid {
background:
repeating-linear-gradient(var(--c1), var(--c1) 1px, transparent 1px, transparent 20px),
repeating-linear-gradient(90deg, var(--c1), var(--c1) 1px, transparent 1px, transparent 20px);
}僅此而已,我們就能得到一個網(wǎng)格圖。
好的,接下來,需要利用 transform 讓他呈現(xiàn)一種 3D 視覺:
body {
perspective: 300px;
}
.grid {
position: absolute;
width: 300vw;
height: 600px;
left: -100vw;
top: 55vh;
transform-style: preserve-3d;
background:
repeating-linear-gradient(var(--c1), var(--c1) 1px, transparent 1px, transparent 20px),
repeating-linear-gradient(90deg, var(--c1), var(--c1) 1px, transparent 1px, transparent 20px);
transform: translate3d(0, 0, 0) rotateX(90deg);
transform-origin: 50% 0;
}效果如下:
由于,整體繞 X 軸旋轉 90°,所以這里的 top: 55vh 很重要。
由于旋轉圓心是 50% 0,如果是 top: 50vh, 相當于整個圖形會垂直于屏幕,如果 top 值小于 50vh,則整個網(wǎng)格是一種向上的翻轉效果:
接著,我們需要讓其運動起來。
我們嘗試添加一個 translateZ 的運動動畫:
.grid {
// ...
animation: move 10s infinite linear;
}
@keyframes move {
0% {
transform: translate3d(0, 0, -600px) rotateX(90deg);
}
100% {
transform: translate3d(0, 0, 600px) rotateX(90deg);
}
}看看效果:
這里有個很嚴重的問題,僅僅只是單個動畫,很難做到無限循環(huán)銜接。
因此,我們需要再加一組 Grid,動畫兩組動畫先后出發(fā),來實現(xiàn)整個動畫的銜接。
.grid {
// ...
animation: move 10s infinite linear;
}
.grid:nth-child(2) {
animation: move 10s infinite -5s linear;
}
@keyframes move {
0% {
transform: translate3d(0, 0, -600px) rotateX(90deg);
}
100% {
transform: translate3d(0, 0, 600px) rotateX(90deg);
}
}我們通過這么一種方式:
- 兩組一模一樣的動畫,整個位移長度是 1200px,整個動畫持續(xù) 10s,緩動為線性動畫。
- 第一組出發(fā) 5s 后(剛好行進了 600px),第二組再出發(fā),如此 infinite 反復。
- 整個 3D 動畫,在近屏幕端看上去就是無限循環(huán)的一種效果。
- 這里運用的是-5s,意思是提前 5s 出發(fā),實際動畫效果也就不會有等待感。
如下(這里,為了錄制 GIF,我整體是加快了動畫的速度):
可以看到,近屏幕端的動畫是連續(xù)不斷的,只是遠端會出現(xiàn)一定的閃爍。這里,可以得到技巧 5。
技巧 5:利用 2 組動畫可以將一些有效在單組內(nèi)的動畫無法實現(xiàn)的連續(xù)效果實現(xiàn)。
這樣,疊加上上面的效果,我們就得到了這樣一種效果:
可以看到,很接近了。目前線條動畫遠處還有一些抖動。剛好,我們還差一個山峰的效果,可以把這塊瑕疵擋住。
使用 box-shadow 及 SVG 濾鏡實現(xiàn)山脈效果
OK,最后,我們在屏幕中間再疊加上一個山峰的效果就好。
這里,原效果使用的是一長串導出的 SVG 路徑。如果我們沒有這種資源,只是想簡單模擬一下效果。這里我給出一種可能可行的方案。
我首先利用一個圓角矩形進行旋轉,再配合容器的 overflow: hidden 得到一個小山峰:
.g-mountain {
position: absolute;
left: 0;
right: 0;
top: 15%;
bottom: 42%;
overflow: hidden;
&::after {
content: "";
position: absolute;
top: 78%;
background: #011d3f;
width: 15vw;
height: 15vw;
transform: rotate(-45deg);
}
}大概是這樣一種效果:
好,如果我們想重復得到多個這樣的圖形,該怎么辦呢?多個 DOM 嗎?不是的,這里我們可以利用 box-shadow 復制自身。
.g-mountain {
// ...
&::after {
content: "";
position: absolute;
top: 78%;
background: #011d3f;
width: 15vw;
height: 15vw;
transform: rotate(-45deg);
box-shadow:
-3vw -3vw, 5vw 5vw,
10vw 10vw 0 3vw, 15vw 20vw 0 4vw,
22vw 22vw 0 6vw, 25vw 30vw 0 12vw,
38vw 36vw 0 1vw, 41vw 39vw 0 3vw,
45vw 45vw 0 2vw, 52vw 52vw 0 4vh,
55vw 55vw 0 1.5vw, 61vw 61vw 0 0.5vw, 68vw 68vw 0 0;
}
}這樣,我們就用一個標簽,實現(xiàn)了一系列的“山”:
這里,我們得到了技巧 6。
技巧 6:box-shadow 可以有效的復制自身,并且,可以利用第四個參數(shù),擴散半徑,來等比例放大自身。
其實,到這里,一個比較粗糙的還原就完成了。當然,有一點小問題是,山峰明顯不應該是一條條直線。能否營造出一種彎彎曲曲的外輪廓效果呢?
這個使用純 CSS 是比較難實現(xiàn)的,當然,好在這里我們可以運用上之前給大家多次提及過的 SVG 濾鏡。
利用 feTurbulence 可以有效實現(xiàn)一些波形紋理效果。并且可以通過 CSS filter 快速引入。
.g-mountain {
// ...
filter: url('#filter');
&::after {
}
}這里,原本,整齊劃一的直線,立馬變得雜亂無章了起來,看起來更像是山脈的輪廓:
這里,我們得出了技巧 7。
技巧 7:SVG 濾鏡可以通過 CSS 濾鏡快速引入,SVG 濾鏡可以實現(xiàn)一些 CSS 完成不了的事情,譬如一些特殊的紋理,波紋,煙霧顆粒感等等效果。
好,至此,我們就大體上按照自己的理解,重新實現(xiàn)了一遍上述的動畫,再做一些簡單的修飾,最終的效果如下:
CodePen Demo -- Pure CSS to the future[2]。
最后
今天的內(nèi)容有點多,技巧也很猛。文中所有技巧在我過往的文章中都有非常高頻的出現(xiàn)次數(shù),對其中細節(jié)不了解的可以在 iCSS 中通過關鍵字查找,好好補一補。
好了,本文到此結束,希望本文對你有所幫助 ????
更多精彩 CSS 技術文章匯總在我的 Github -- iCSS[3] 。
參考資料
[1]CodePen DEMO -- to the future By Jane Ori: https://codepen.io/propjockey/pen/VwKQENg。
[2]CodePen Demo -- Pure CSS to the future: https://codepen.io/Chokcoco/pen/eYrOmaK?editors=1100。
[3]Github -- iCSS: https://github.com/chokcoco/iCSS。
網(wǎng)站欄目:高階CSS技巧在復雜動效中的應用
標題路徑:http://m.fisionsoft.com.cn/article/ccichoc.html


咨詢
建站咨詢
