手把手教你擼出跑男動畫 CSS3-Animation抽絲剝繭

LucasHC發表於2017-03-14

作為一名真正的前端開發者,我們不能只關注前端邏輯部分。畢竟“水銀洩地”般的頁面設計和“炫酷逼真”的動畫效果,是我們區別於其他程式設計師所特有的優勢之一。

儘量百分之百的還原視覺稿,為UE設計靈感和使用者視覺享受架起一座橋樑:正所謂“晉帝時祭北郊,更祝版,工人削之,筆入木三分。”
借古書法形容我們的程式碼,當真是恰當準確又自戀無比。

之前的一些文章大多都是分享JS相關內容。今天輕鬆一下,我來談談前端頁面的動畫部分。通過剖析一個“跑男”動畫例項,來把CSS3中動畫相關的知識點抽絲剝繭,一網打盡。如果讀者有自己的感想或者不一樣的見解,歡迎一起討論。

整個專案的Github地址可以參考這裡。對比線上效果,這個倉庫進行了90%的刪減,但是更加適合練手和理解。感興趣的讀者歡迎拉下來自己玩一玩。裡面只有一關動畫,您可以比葫蘆畫瓢進行除錯練習。

專案簡介

這是一個運營活動頁面——"春季馬拉松大比拼":使用者以闖關形式參加,並進行角色扮演。在滿足一定條件下,自己扮演的馬拉松選手會繞著跑道(非正規跑道形狀)前進,向終點發起衝擊。

部分頁面動畫效果如下:

手把手教你擼出跑男動畫  CSS3-Animation抽絲剝繭
部分動畫效果截圖

當然,這個動畫並不完美。考慮到時間價效比,我只用了兩幀重複迴圈模擬擺腿動作。但也達到了運營和產品小妹的需求。如果在沒有上線壓力的情況下,我們完全可以拆分更多幀,把他打磨的更流暢順滑。

首先,我們來看一下它的具體實現方式吧。

動畫方案

這一系列的動畫設計,出於效能和簡單的考慮,我採用了純CSS3來實現。CSS3實現動畫,主要有兩種方式:transition屬性和animation屬性。
前者是用來“平滑的改變CSS的值”。一般對於需要特定幀處理的動畫,顯然是蒼白無力的,這裡就不過多介紹了。重點介紹一下animation屬性。

animation

animation屬性其實是一個簡寫屬性,就像我們更加熟悉的“background”一樣。它用於設定六個動畫屬性:

1)animation-name
2)animation-duration
3)animation-timing-function
4)animation-delay
5)animation-iteration-count
6)animation-direction

最重要的就是animation-name,它規定了需要繫結的keyframes名稱。keyframes,我們用來定義幾個關鍵節點幀。

具體我不會進行科普。如果初學者不瞭解,社群上關於這些的資料可是一大把。

跑男開跑

回到具體的業務場景,我們進行分析。跑男的動畫其實可以拆分為兩個:
1)一個是交替擺腿;
2)另一個是位置移動。
這兩個動作要嚴絲合縫的結合。能把這個想清楚,那就基本思路理解了。

接著,如何讓這兩種動畫一起施加在“靜止的”跑男身上呢?

我採用了增加一個div標籤,作為父節點包裹的方式:

<div class="man-wrapper" id="man-wrapper">
    <div class="man" id="man"></div>
</div>複製程式碼

'man-wrapper'這個div與'man'這個div尺寸大小完全一致,視覺上絕對重合。父節點處理位移,子節點負責交替擺腿:

.man-wrapper {
    display: inline-block;
    width: 46px;
    height: 75px;
    position: absolute;
}
.man {
    display: inline-block;
    width: 46px;
    height: 75px;
    background: url(img/sprite.png);
    position: absolute;
    top: 0;
    left: 0;
}複製程式碼

當需要觸發位移,開啟跑步狀態時,父節點添"start-run"類:

$('.man-wrapper').addClass('start-run');複製程式碼

同時,子節點新增"running"類:

$('#man').addClass('running');複製程式碼

動畫實現

關於“start-run”位移的動畫設計,在跑道上直道部分相對簡單,我們思路是使用transform:translate3d。
但是視覺稿上存在不少於5處不規則彎道,在不改變原圖的基礎上,以及在不增加多餘圖片的原則下,我們可以使用transform:rotate3d,使跑男進行側身。具體設計看下圖:

手把手教你擼出跑男動畫  CSS3-Animation抽絲剝繭
動畫部分分解

1)1-2和4-5,只需要改變transform:translate3d;
2)2-4部分,即2,3,4這三個階段是為了彎道準備的。當然,如果時間充足,我們完全可以拆分的更加細緻,更加細分。
3)其中3是彎道中心的45度轉身:rotate3d(0,0,1,45deg);
4)其中4是已經完全轉身:rotate3d(0,0,1,90deg);

具體程式碼:

.start-run {
    animation: start-run 5000ms; 
    animation-fill-mode: forwards;
    animation-timing-function: linear;
}
@keyframes start-run {
    0% {
        transform: translate3d(0, 0, 0);
    }
    35% {
        transform: translate3d(0, 155px, 0) rotate3d(0, 0, 1, 0deg);
    }
    50% {
        transform: translate3d(20px, 224px, 0) rotate3d(0, 0, 1, -45deg);
    }
    70% {
        transform: translate3d(80px, 242px, 0) rotate3d(0, 0, 1, -90deg);
    }
    100% {
        transform: translate3d(200px, 243px, 0) rotate3d(0, 0, 1, -90deg);
    }
}複製程式碼

為什麼是35%,50%,70%呢?這個是我除錯出來,相對能達到順暢效果。如果追求更嚴謹的話,完全可以列一個極座標計算一下位移和時間。當然這樣子成本會比較大。

還有一點值得一提的是animation-timing-function: linear; 一般馬拉松中段,都近似於勻速跑吧~

解決完了位移的問題,我們來看擺腿動作。這個其實就是兩張圖片在交替播放。就是gif圖原理。我使用了改變background-position,來切換精靈圖片的方式處理:

.running {
    animation: running-man 1200ms steps(2) infinite;
}
@keyframes running-man {
    0% {
        background-position: 0 0;
    }
    50% {
        background-position: 92px 0;
    }
}複製程式碼

千萬不要掃一眼程式碼完事兒,這裡還有一些最重要的細節要注意。首先是“infinite”的使用,這個應該沒什麼意外吧。另外,你可曾注意了steps這個函式?

steps()函式實現階躍動畫

我們知道animation定義的關鍵幀之間是“平滑過渡”的。這個平滑過渡怎麼理解呢?我做了一個“反例”示圖來說明。
在使用keyframes改變雪碧圖background-position時,得到效果:

手把手教你擼出跑男動畫  CSS3-Animation抽絲剝繭
動畫部分分解反面示例

這樣的"平滑過度"顯然不是我們想要的。

所以,在切換雪碧圖背景的方案下,steps()就要派上用場了。順便說一句,最近面試一些人,提到熟悉CSS3動畫,但是大部分都還不知道這個steps階躍函式。如果你還不清楚,可以參考這裡。

藉助steps()函式,我們實現了交替跑動的分解動畫:

手把手教你擼出跑男動畫  CSS3-Animation抽絲剝繭
動畫部分分解

還不完美

做到這裡,其實還沒有完全結束。有一些值得我們思考的問題。

1)真的有必要多一個標籤,來相互結合生成動畫嗎?
其實不是的,animation很神奇很強大的一點在於:它可以接受多個動畫屬性序列。比如上邊那種情況我們完全可以這樣實現:

.running {
    animation: start-run 5000ms forwards linear, running-man 1200ms steps(2) infinite
}複製程式碼

2) 如果刻意追求更佳完美的動畫,我們還需要哪些儲備?
不得不要說數學和物理知識了。比如,二次方曲線、三次方曲線、一直到五次方曲線,正弦餘弦、圓弧、拋物線、反彈曲線、彈簧曲線等等。如果你對研究這些有興趣,這裡安利一些:高效能動畫實現以及視覺化1視覺化2。

除了數學公式以外,也需要我們掌握樣式前處理器函式使用。畢竟,那麼多幀我們不可能自己手動實現。

總結

流暢高效的動畫,絕非一朝一夕就能完成,需要各方面甚至跨領域的積累。如果你對此很感興趣,歡迎討論。

最後,這篇文章中截圖部分採用了我廠UE:許冬設計師的視覺稿,和PM:田小甜大小姐的互動設計。

PS:百度知識搜尋部大前端繼續招兵買馬,有意向者火速聯絡。。。

相關文章