如何使用CSS創(chuàng)建高級(jí)動(dòng)畫(huà),這個(gè)函數(shù)必須掌握
我們每天都在網(wǎng)上摸魚(yú),作為前端開(kāi)發(fā)人員,網(wǎng)站上微妙的細(xì)節(jié)變化通過(guò)比別人會(huì)更關(guān)注。我一直注意到的一件事是網(wǎng)站上的動(dòng)畫(huà)的流暢性。動(dòng)畫(huà)對(duì)于用戶體驗(yàn)來(lái)說(shuō)是非常好的,有時(shí)我們可以一些有趣的動(dòng)畫(huà)來(lái)留住用戶。
創(chuàng)建高級(jí)動(dòng)畫(huà)聽(tīng)起來(lái)是一個(gè)很難的話題,但好消息是,在CSS中,可以將多個(gè)簡(jiǎn)單的動(dòng)畫(huà)相互疊加,以創(chuàng)建一個(gè)更復(fù)雜的動(dòng)畫(huà)
在這節(jié)課中,我們會(huì)學(xué)習(xí)如下幾點(diǎn):
- 什么是貝塞爾曲線,以及如何用一行CSS來(lái)創(chuàng)建一個(gè) "復(fù)雜"的動(dòng)畫(huà)
- 如何將動(dòng)畫(huà)相互疊加以創(chuàng)建一個(gè)高級(jí)動(dòng)畫(huà)
- 如何通過(guò)應(yīng)用上面學(xué)到的兩點(diǎn)來(lái)創(chuàng)建一個(gè)過(guò)山車動(dòng)畫(huà)
什么是貝塞爾曲線
CSS中的 cubic-bezier 函數(shù)是一個(gè)緩動(dòng)函數(shù),可以讓我們完全控制動(dòng)畫(huà)在時(shí)間上的表現(xiàn)。下面是官方的定義:
貝塞爾緩動(dòng)函數(shù)是一種由四個(gè)實(shí)數(shù)定義的緩和函數(shù),指定了貝塞爾曲線的兩個(gè)控制點(diǎn)P1和P2,其端點(diǎn)P0和P3分別固定在(0, 0)和(1, 1)。P1和P2的x坐標(biāo)被限制在[0, 1]范圍內(nèi)。
什么是緩動(dòng)函數(shù)?
線性曲線
想象兩個(gè)點(diǎn)P0和P1,其中P0是動(dòng)畫(huà)的起點(diǎn),P1是結(jié)束點(diǎn)?,F(xiàn)在想象另一個(gè)點(diǎn)在兩點(diǎn)之間線性移動(dòng),如下所示
這就是所謂的線性曲線,也是最簡(jiǎn)單的動(dòng)畫(huà)。
二次貝塞爾曲線
如下圖所示,有三個(gè)點(diǎn)。P0、P1和P2。我們想讓動(dòng)畫(huà)從P0?移動(dòng)到P2?。在這種情況下,P1?是一個(gè)控制點(diǎn),控制動(dòng)畫(huà)的曲線。
二次方貝塞爾概念:
- 在P0和P1之間以及P1和P2之間(用灰線表示)連接虛線
- 點(diǎn)Q0沿著P0和P1之間的直線移動(dòng)。同時(shí),點(diǎn)Q1沿著P1和P2之間的直線移動(dòng)
- 在Q0和Q1之間連接一條虛線(用綠線表示)
- 在Q0和Q1開(kāi)始移動(dòng)的同時(shí),點(diǎn)B開(kāi)始沿著綠線移動(dòng),B點(diǎn)所走的路徑就是動(dòng)畫(huà)路徑
請(qǐng)注意,Q0、Q1和B不以相同的速度移動(dòng)。它們都必須在同一時(shí)間開(kāi)始,并在同一時(shí)間完成它們的路徑。因此,每一個(gè)點(diǎn)都是根據(jù)它所移動(dòng)的線長(zhǎng)以適當(dāng)?shù)乃俣纫苿?dòng)的。
三次貝塞爾曲線
三次貝塞爾曲線由4個(gè)點(diǎn)組成。P0, P1, P2和P3。動(dòng)畫(huà)開(kāi)始于P0,結(jié)束于P3。P1和P2是我們的控制點(diǎn)。
三次貝賽爾的工作原理如下:
- 在(P0, P1)、(P1, P2)和(P2, P3)之間連接虛線,由灰線表示
- 點(diǎn)Q0、Q1和Q2分別沿直線(P0,P1)、(P1,P2)和(P2,P3)移動(dòng)
- 在(Q0, Q1)和(Q1, Q2)之間連接虛線,它們由綠線表示。
- 點(diǎn)R0和R1分別沿直線(Q0, Q1)和(Q1, Q2)移動(dòng)
- 連接R0和R1之間的線(用藍(lán)線表示)
- 最后,B點(diǎn)沿著R0和R1之間的連接線移動(dòng),B點(diǎn)所走的路徑就是動(dòng)畫(huà)路徑
如果你想更好地了解三次體貝塞爾的工作原理,建議你看看這個(gè)desmos鏈接。玩玩控制點(diǎn),看看動(dòng)畫(huà)如何隨時(shí)間變化。(注意,鏈接中的動(dòng)畫(huà)是由黑線表示的)。
疊加動(dòng)畫(huà)
有很多步驟的大動(dòng)畫(huà)可以被分解成多個(gè)小動(dòng)畫(huà)。在 css 中,通過(guò)添加??animation-delay?
?屬性來(lái)實(shí)現(xiàn)這一點(diǎn)。計(jì)算延遲很簡(jiǎn)單,把你要計(jì)算動(dòng)畫(huà)延遲的那個(gè)動(dòng)畫(huà)之前的所有動(dòng)畫(huà)的時(shí)間加起來(lái)。
例如:
這里,我們有兩個(gè)動(dòng)畫(huà),movePointLeft和movePointDown。movePointLeft的動(dòng)畫(huà)延遲是零,因?yàn)樗俏覀兿胂冗\(yùn)行的動(dòng)畫(huà)。movePointDown的動(dòng)畫(huà)延遲是4秒,因?yàn)閙ovePointLeft將在這段時(shí)間后完成。
因此,animation-delay屬性:
注意,如果有兩個(gè)或更多的動(dòng)畫(huà)同時(shí)開(kāi)始,它們的動(dòng)畫(huà)延遲將是一樣的。此外,當(dāng)你計(jì)算即將開(kāi)始的動(dòng)畫(huà)的延遲時(shí),把它們視為一個(gè)動(dòng)。例如 :
假設(shè)x和y同時(shí)開(kāi)始。在這種情況下,x和y的動(dòng)畫(huà)延遲都將為零,而 jump 動(dòng)畫(huà)的延遲將為4秒(而不是8秒?。?。
創(chuàng)建過(guò)山車
掌握了上面的知識(shí),是時(shí)候應(yīng)用一下了。
了解動(dòng)畫(huà)
過(guò)山車路徑由三部分組成:
- 滑動(dòng)部分
- 循環(huán)部分
- 還會(huì)有一些動(dòng)畫(huà),在上面的兩個(gè)動(dòng)畫(huà)之間創(chuàng)造水平空間
我們將首先創(chuàng)建一個(gè)簡(jiǎn)單的球,作為我們過(guò)山車的 "車"。
hmtl 部分:
css 部分:
滑動(dòng)部分
創(chuàng)建小球滑動(dòng)的部分可以用cubic-bezier函數(shù)來(lái)完成! 這個(gè)動(dòng)畫(huà)是由2個(gè)動(dòng)畫(huà)組成的,一個(gè)是沿x軸的動(dòng)畫(huà),另一個(gè)是沿y軸的動(dòng)畫(huà)。X軸動(dòng)畫(huà)是一個(gè)沿X軸的普通線性動(dòng)畫(huà)。它的關(guān)鍵幀如下:
將其添加到球路徑的 animation 屬性中,如下所示
y軸動(dòng)畫(huà)是我們將使用cubic-bezier函數(shù)的部分。首先定義動(dòng)畫(huà)的關(guān)鍵幀。我們希望起始點(diǎn)和結(jié)束點(diǎn)之間的差異很小,以至于球達(dá)到的高度幾乎相同。
現(xiàn)在讓我們來(lái)思考一下cubic-bezier函數(shù)。我們希望我們的路徑先向右緩慢移動(dòng),然后當(dāng)它滑動(dòng)時(shí),它應(yīng)該走得更快。
- 向右緩慢移動(dòng)意味著$P1$將沿x軸移動(dòng)。所以,我們知道它是在(V,0)。
- 我們需要選擇一個(gè)合適的V,使我們的動(dòng)畫(huà)緩慢地向右移動(dòng),但又不能太多,以免占用整個(gè)空間。在這種情況下,我發(fā)現(xiàn)0.55最適合。
- 為了達(dá)到滑動(dòng)效果,我們需要將P2向Y軸下移(負(fù)值),所以P2=(X,-Y)。
Y應(yīng)該是一個(gè)大值。在這種情況下,我選擇Y=5000。
為了得到X,我們知道我們的動(dòng)畫(huà)速度在滑動(dòng)時(shí)應(yīng)該更快,在再次上升時(shí)應(yīng)該更慢。所以,X越接近于零,動(dòng)畫(huà)在滑動(dòng)時(shí)就越陡峭。在這種情況下,讓X = 0.8。
現(xiàn)在,我們得到了一個(gè)cubic-bezier函數(shù):
為動(dòng)畫(huà)屬性添加關(guān)鍵幀:
這是我們動(dòng)畫(huà)的第一部分,所以動(dòng)畫(huà)延遲為零。我們應(yīng)該添加一個(gè)animation-delay屬性,因?yàn)閺南旅娴膭?dòng)畫(huà)開(kāi)始,動(dòng)畫(huà)的開(kāi)始時(shí)間將與第一個(gè)動(dòng)畫(huà)不同。
地址:https://codepen.io/smashingmag/pen/VwxXBQb
添加水平空間
在做循環(huán)之前,球應(yīng)該沿著??X?
?軸移動(dòng)一小會(huì)兒,所以兩個(gè)動(dòng)畫(huà)之間有空間。
定義關(guān)鍵幀
把它添加到 ??animation?
?
這個(gè)動(dòng)畫(huà)應(yīng)該在滑動(dòng)動(dòng)畫(huà)之后開(kāi)始,而滑動(dòng)動(dòng)畫(huà)需要4秒,因此,動(dòng)畫(huà)延遲將是4秒。
地址:https://codepen.io/smashingmag/pen/dyemExY
循環(huán)部分
要在CSS中創(chuàng)建一個(gè)圓(循環(huán)),我們需要把圓移到循環(huán)的中心,然后從那里開(kāi)始做動(dòng)畫(huà)。圓的半徑是100px,所以我們把圓的位置改為top: 20vh(30是期望的半徑(這里是10vh))。然而,這需要在滑動(dòng)動(dòng)畫(huà)完成后發(fā)生,所以我們將創(chuàng)建另一個(gè)持續(xù)時(shí)間為0秒的動(dòng)畫(huà),并添加一個(gè)合適的動(dòng)畫(huà)延遲。
關(guān)鍵幀:
添加到 animation 動(dòng)畫(huà)中:
添加動(dòng)畫(huà)延遲, 4.5s:
循環(huán)本身
創(chuàng)建一個(gè)循環(huán)動(dòng)畫(huà):
- 創(chuàng)建一個(gè)關(guān)鍵幀,將球移回原來(lái)的位置,然后旋轉(zhuǎn)球。
添加到 animation 中:
添加動(dòng)畫(huà)延遲,這里是4.5s:
地址:https://codepen.io/smashingmag/pen/mdLxZdR
添加水平空間
快完成了,最后 只需要在動(dòng)畫(huà)之后沿著??x?
?軸移動(dòng)球,這樣球就不會(huì)像上圖中那樣在循環(huán)之后完全停止。
關(guān)鍵幀:
添加到 animation 中:
加上適當(dāng)?shù)难舆t,這里是7.5s:
地址:https://codepen.io/smashingmag/pen/wvjmLKp
總結(jié)
在本節(jié)中,我們介紹了如何結(jié)合多個(gè)關(guān)鍵幀來(lái)創(chuàng)建一個(gè)復(fù)雜的動(dòng)畫(huà)路徑。我們還介紹了貝塞爾以及如何使用它們來(lái)創(chuàng)建你自己的緩動(dòng)函數(shù)。建議大家自己多多動(dòng)手,才能更好的掌握 css 動(dòng)畫(huà)。
來(lái)源:https://www.smashingmagazine.com/2022/10/advanced-animations-css/