最近,群友貼了一個非常有意思的動畫效果,整體動畫效果如下:
點選某個按鈕後,觸發一個動畫效果,原本的網格內容,將按順序(又帶點隨機的效果)從高處下落進行載入填充動畫。
當然,我個人認為這個動畫有點華而不實,主要體現在這個動畫一次需要耗費較長時間,有點消磨人的耐心。不過確實一個很好的 CSS 動畫教學案例。
而本文,就將具體去剖析這個動畫,如果使用純 CSS,應該如何實現。
首先,我們需要大致還原佈局結構,這個並非整個動畫的核心。
整個動畫的核心在於元素按順序(又帶點隨機的效果)從高處下落漸次進行下落載入填充動畫。
當然,還原這個佈局也非常簡單,這裡我們藉助 flex 佈局快速實現,幾個關鍵點:
justify-content: center;
即可這樣,整個佈局的大致程式碼如下:
<ul>
<li></li>
<li></li>
// ... 假設一共 50 個 li
<li></li>
</ul>
$count: 51;
@function randomNum($max, $min: 0, $u: 1) {
@return ($min + random($max)) * $u;
}
@function randomColor() {
@return rgb(randomNum(255), randomNum(255), randomNum(255));
}
ul {
display: flex;
gap: 4px;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
width: 640px;
height: 420px;
}
li {
flex-shrink: 0;
height: 30px;
border-radius: 30px;
}
@for $i from 1 to $count {
li:nth-child(#{$i}) {
width: #{randomNum(110, 90)}px;
background: randomColor();
}
}
簡單解釋一下:
randomNum()
: 用於生成範圍內的亂數randomColor()
: 用於生成隨機顏色值這樣,我們就可以快速得到這樣一個佈局效果:
接下來,我們來實現元素的下落動畫。
首先,我們撇開多元素的按順序又帶點隨機的延遲下落,值聚焦於單個 item 的下落動畫,它其實是這麼個動畫效果:
整個動畫的核心步驟大致是:
animation-fill-mode: forwards
)對 CSS 動畫細節和各個屬性還不太瞭解的,建議你看看我的這本小冊 -- CSS 技術揭祕與實戰通關
完成上面的拆解後,單個動畫實現起來就非常輕鬆了:
li {
opacity: 0;
&hover {
animation: falldown 1s forwards;
}
}
@keyframes falldown {
0% {
transform: translateY(-180px) scaleX(.1) scaleY(.3);
opacity: 1;
}
20% {
transform: translateY(-200px) scaleX(.6) scaleY(.3);
}
75% {
transform: translateY(0) scaleX(.6) scaleY(.3);
}
100% {
transform: translateY(0) scaleX(1) scaleY(1);
opacity: 1;
}
}
這樣,我們就輕鬆的實現了單個的動畫效果:
如果 50 個 item 同時作用這個動畫,就是這樣的效果:
當然,到這裡,整個動畫都還是平平無奇的。
我們需要最後的點睛之筆,實現按順序又帶點隨機的延遲下落效果,以及讓整體的動畫更加自然。
這裡的核心就在於:
animation-delay
製造延遲效果,但是不能是順序延遲,需要帶點隨機效果animation-timing-function
緩動函數,控制動畫的速度曲線,使動畫變化更為平滑方法明確了,剩下的就是偵錯動畫效果了,最終,經過一番偵錯,完整的動畫效果的程式碼就完成啦。
程式碼量真的不多:
$count: 51;
@function randomNum($max, $min: 0, $u: 1) {
@return ($min + random($max)) * $u;
}
@function randomColor() {
@return rgb(randomNum(255), randomNum(255), randomNum(255));
}
ul {
display: flex;
gap: 4px;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
width: 660px;
height: 420px;
}
li {
flex-shrink: 0;
height: 30px;
border-radius: 30px;
}
@for $i from 1 to $count {
li:nth-child(#{$i}) {
width: #{randomNum(110, 90)}px;
background: randomColor();
}
}
ul:hover {
li {
opacity: 0;
}
@for $i from 1 to $count {
li:nth-child(#{$i}) {
animation: falldown .3s cubic-bezier(.44,.02,.65,1.3) #{50 * ($count - $i) + (random(150) - random(300))}ms forwards;
}
}
}
@keyframes falldown {
0% {
transform: translateY(-180px) scaleX(.1) scaleY(.3);
opacity: 1;
}
20% {
transform: translateY(-200px) scaleX(.6) scaleY(.3);
}
75% {
transform: translateY(0) scaleX(.6) scaleY(.3);
}
100% {
transform: translateY(0) scaleX(1) scaleY(1);
opacity: 1;
}
}
核心,就在於這一句,animation: falldown .3s cubic-bezier(.44,.02,.65,1.3) #{50 * ($count - $i) + (random(150) - random(300))}ms forwards
,需要好好的消化理解。
這樣,我們就基本完美的復刻了原效果:
Gif 錄製存在掉幀行為,原效果會比 GIF 錄製出來的更好。完整的程式碼你可以戳這裡:
CodePen Demo -- Flex Item Fall Down
好了,本文到此結束,希望對你有幫助