譯文\譯者鞠大寶
先有UI動畫,然后才會有好的UI動畫。好的動畫會讓人驚嘆“哇哦!”——因為頁面看上去很流暢、很漂亮,最重要的是,自然,一點都不會讓人覺得不和諧或者僵硬死板。如果你經常逛Dribbble或者 UpLabs這類網站的話,你就會明白我在說什么了。
一些極好的拓展閱讀資源:
·SVG和CSS的路徑剪輯動畫
·若干實用的動畫技術
·使用SVG手繪動畫
·新的網頁動畫API
既然有這么多天才設計師創造了如此漂亮的動畫,自然是任何開發者都會想要在自己的項目中引進這些效果。如今,CSS為transition-timing-function提供了一些預置變量,比如ease-in, ease-out 和 ease-in-out, 它們將頁面的平滑感和真實感提升了一個檔次,但是,你不覺得這個方法太大眾化了嗎?試想如果頁面上的每個動畫都用了這3個相同的時間變量,那該是有多乏味啊。
(引自: Lukáš Straňák)
transition-timing-function有一個變形是cubic-bezier(n1, n2, n3, n4), 你可以傳進4個參數來創建自己獨一無二的時間函數。在這篇文章的最后,你將會看到這4個參數各自代表什么——但是,相信我,要找到四個數字來捕獲你想象中的轉變並不是一件容易事兒。 幸虧有cubic-bezier和Ceasar, 你不必非得自己來完成。這些工具將運動曲線引入到了網頁中。
(引自: m-2-h)
運動曲線最早是被動畫師們用來創造先進、逼真的動畫(比如 Adobe After Effects)。通過cubic-bezier 和Ceasar, 你可以很容易地操縱曲線的形狀,另外 (n1, n2, n3, n4) 這4個數字也會為你填好,這絕對超贊! 盡管如此,如果使用時想要最大化運動曲線的功能,你則需要了解它們的工作原理,這就是我們接下來在這篇文章中要講到的。現在我們開始吧。
理解運動曲線
運動曲線其實只是連接 動畫屬性 和時間的一個點。一條運動曲線展示了一個動畫運動的速度是如何受時間的影響並隨之變化的。
運動曲線是連接動畫屬性和時間的一個點。
讓我們拿 distance (translateX) 作為動畫屬性舉例。(這個解釋同樣適用於其他的任何一個動畫屬性。)
在一張距離-時間圖上計算t1時刻的速度。
如果你有一定的物理學和初級微積分學的基礎,你就會知道從一張距離-時間表上算出速度是非常容易的。表中的單位時間內走過的距離除以單位時間得到的某時刻的導數,就是速度。 也就是說,距離-時間曲線上的物體在曲線陡峭的地方有更快的運動速度,而在曲線平緩的地方,速度則比較慢。如果你知道它的原理,那太棒了!說明你已經做好了充足的准備,可以跳過下面這節。
如今,我意識到設計和開發是完全不同的領域,畢竟不是每個人都有相同的背景。 也許上面那段話你完全聽不懂,也用不着灰心喪氣,因為我接下來會慢慢解釋的。
看到下面的紅盒了嗎?請允許我童心未泯地將之稱為“Boxy”;這樣提及它時會更方便一些。好了,我們可以看到Boxy正在以線性的方式從屏幕的一邊移動到另一邊,接下來我們來分析一下它的運動。
transition-timing-function 的一個預置參數是linear。為了讓Boxy動起來,我們要做的就是添加下面的這個方法。
.moveForward {
transform: translateX(1000px);
}
為了控制動畫效果,我們會為Boxy設transition屬性,如下所示:
#boxy { width: 200px; height: 200px; background: red; transition-property: transform; transition-duration: 1s; transition-timing-function: linear; }
想要將transition解釋清楚是一件很麻煩的事情,實際上,你將會發現transition都是用速記形式寫的:
#boxy {
width: 200px;
height: 200px;
background: red;
transition: transform 1s linear;
}
看它動起來的效果。查看
紅盒在做直線運動。
它看上去很像一個機器人,不是嗎?當然你可以說它之所以看上去很機械,完全是因為它做的是直線運動,這聽起來好像很合理。但是你又要如何解釋導致這一現象的原因呢?我們可以看到直線運動使得物品的移動顯得很機械,但是隱藏在屏幕后面的工作原理又是什么呢?所以,我們的當務之急就是搞清楚為什么這樣的移動會讓人覺得很機械、不和諧又不自然。
讓我們將Boxy的移動用坐標軸來展現,看看是否能得到一些有用的信息。坐標軸有兩根軸線,縱軸表示距離,橫軸表示時間。Boxy在1秒鍾內走過了1000像素的距離。 我們接下來會用到一些數學知識,不過不用擔心,因為都很簡單。
這就是我們建的非常簡易的圖表,上面有兩根坐標軸, 正如我剛剛提到的那樣。
只有坐標軸的空表
現在,它是空的,讓我們填進去一些數據。
首先,我們可以看到在初始時刻(也就是0秒時),動畫還沒有開始,Boxy處在它的初始位置(也就是0像素的位置)。1秒鍾過后,Boxy一共運動了1000像素,停在了初始位置的對面。
Boxy的起點和終點位置。
讓我們在圖中標出數據。
標有Boxy起點和終點位置的圖表
到現在為止一切都很順利。但是只有兩個點的數據遠遠不夠——我們需要更多。接下來的數據記錄了Boxy在不同時間點的所處位置(這一切都多虧了我的高速攝像機)。
不同時間點Boxy所處的位置
我們將這些數據添加到坐標軸中。
標有不同位置的坐標軸。
當然,你也可以搜集更多不同時刻的點(比如0.375s、0.6s等等),但是我們現在有的已經足夠來建成這張表了。標注了上面的所有點后,我們的表就建成啦。來,擊個掌!
坐標軸最終版本
酷!但是我們能從這得到什么呢?我們要時刻記住,實驗的目的是弄明白為什么Boxy的線性運動看上去會不自然並且很機械。很顯然,我們建好的這張表還不能告訴我們這是為什么。我們需要更深入地探索。
讓我們記住這張表,然后花1分鍾時間來討論一下速度。我相信你應該了解速度的概念——我指的就是數學術語上的速度。它的計算方法如下所示:
計算速度的數學公式
因此,如果一輛卡車在1小時內行駛100公里,我們就說它的速度是100km/h。
速度的計算
如果這輛卡車將速度加倍,他就會在相同的時間間隔1小時內行駛雙倍的距離(也就是200公里),換句話說,要行駛100公里,它現在只需要剛才的一半時間(也就是半個小時)。能理解我的意思嗎?
類似的,如果這輛卡車將它的速度減半,它將在相同的時間段1小時內走過50公里,也就是說,要行駛100公里,它將需要雙倍時間(也就是2個小時)。
好!讓我們回到之前的思路上,我們目前是在嘗試弄清楚這張距離-時間表是如何幫助我們找到Boxy的線性運動看上去很僵硬的原因。
嘿,等一下!我們有一張距離-時間表,並且速度可以通過路程和時間求得,不是嗎?接下來我們就嘗試計算Boxy不同單位時間內的速度。
計算不同單位時間段的速度。
在這里,我挑選了3個不同的時間段:一段靠近起點,一段在中間位置,還有一段是接近終點的位置。很明顯,在這三個時間段內,Boxy速度相同(它運動的路程s1=s2=s3),即1000px/s。由此可見,不管你在上表中選擇的是哪個時間段,你會發現Boxy都是以1000px/s的速度移動的。是不是很意外?現實生活中,沒有物體能夠一直以一個恆定的速度運動;它們起步時速度都比較慢,然后會逐漸增加速度,運動一段時間后,又會在停下來之前減速,但Boxy卻是以1000px/s的速度突然起步,接着做勻速運動,並且恰恰是以相同的速度突然停止。這就是為什么Boxy的移動看上去很機械且不自然,接着我們必須重新繪制我們的坐標系來體現這一點。但是在深入研究之前,我們需要了解速度的改變是如何改變距離-時間表的。准備好了嗎?接下來的探索將會很有趣。
我們將Boxy的速度提升一倍,來看看坐標圖相應地會如何變化。Boxy的初始速度,還是如我們上面計算的那樣是1000px/s。因為我們將它的速度變為了兩倍,Boxy只需一半時間——也就是0.5秒,就可以走完全程。讓我們在坐標圖中畫出來。
兩倍速度時的坐標圖
如果我們將它的速度增加至3倍呢?Boxy只需要三分之一的時間就可以走完全程(也就是1/3秒)。
三倍速度時的坐標圖
嗯,看出什么了嗎?我們可以看到,隨着速度的增長,坐標圖發生變化,這條直線與時間橫軸間的夾角也在不斷增加。
那好,我們繼續將Boxy的速度減半。將它的速度減半意味着Boxy只能在1秒鍾內走過500像素(也就是剛剛距離的一半)。然后讓我們在坐標圖中畫出來。
一半速度時的坐標圖 (點開看大圖)
我們將Boxy的速度再放慢一些,讓它以原本速度的三分之一運動。這樣的話,1秒鍾內Boxy就只能走過一開始走過路程的三分之一。
三分之一速度時的坐標圖 (點開看大圖)
看出規律了嗎?我們增加Boxy的速度時,線條越來越陡峭;而減慢Boxy的速度時,線條又變得平滑。
速度增加時直線變陡,減慢時直線變得平緩。 (點開看大圖)
這個結論很重要,因為對一條很陡的直線而言,也就是速度更快時,一小段時間內Boxy走過的路程會變化很多。
對線段更陡的表而言,小段時間相應會在距離上有很大的改變。 (點開看大圖)
對線段更陡的表而言,小段時間相應會在距離上有很大的改變。(點開看大圖)
另一方面,對於坡度不那么大的直線,就算過去很長時間,距離上也只會變化一點點,這是運動速度比較慢的情況。
坡度比較平緩時坐標圖中時間和距離的變化關系 (點開看大圖)
坡度比較平緩時,坐標圖中時間和距離的變化關系 (點開看大圖)
以上我們所做的只是改變了Boxy的運動速度,它仍然是在做直線運動。但是,我們以新的方式弄清楚了距離和時間是如何改變速度的,接下來就可以繪制一張表來讓Boxy以一種自然、真實的方式運動。
讓我們一步一個腳印。首先,現實生活中的物體都是慢慢開始運動,並且逐漸增加運動速度的。所以,我們來模擬這一過程。
仔細觀察下圖,你會發現起點和終點位置沒有變。因為我們不想改變動畫的持續時間,也不想改變Boxy的運動距離。
私人定制的運動曲線 (點開看大圖)
Boxy如果照着上面的這張圖運動,前0.25秒它的速度會比較慢,因為0秒到0.25秒之間這條線比較平緩,接着它會突然增速(因為0.25秒之后線段突然變陡)。 但是我們需要將這一轉變變得平滑,因為我們不想要任何轉角——畢竟,這是一條運動曲線。接下來就將這個急轉彎換成一條曲線。
私人定制的運動曲線 (點開看大圖)
留心Boxy從靜止狀態到逐漸增速過程中平滑的轉變。
按照上面那條運動曲線運動的Boxy (點開看圖)
很好!實際生活中,運動的物體停下來之前速度也是逐漸減慢的。讓我們修改坐標圖來適應這一變化。類似的,我們會在想要Boxy慢下來的地方增加一個點。就加在0.6秒處怎么樣?我已經將這個轉折點換成曲線了。
運動曲線終極版 (點開看大圖)
看Boxy動起來! 現在看上去自然了很多,不是嗎?
按照終極版運動曲線運動的Boxy (點開看圖)
我們用來代替轉角的曲線實際上是由很多短線段組成的;並且正如你已經知道的,表中的線段越陡峭,Boxy的運動速度就越快,線段越平緩,Boxy的速度就越慢。看坐標圖的左邊部分,會發現組成曲線的小線段坡度越來越大,導致速度逐漸增加;相應地,右邊部分的線段越來越平緩,所以速度才會越來越慢。
一條曲線只是很多的短線段的集合 (點開看大圖)
就以上我們所知道的,想要弄清楚運動曲線容易了很多。接下來我們來看一些例子。
例 1 (點開看圖)
例 2 (點開看圖)
例 3 (點開看圖)
在UI動畫中使用運動曲線
接下來你需要讓一個UI元素動起來,可以將運動曲線為你所用。無論是一個滑桿兒、一個窗口模型,還是一個下拉菜單,增加適量的動畫效果讓它們看上去平滑自然可以大幅度提高你的用戶界面質量。它會讓用戶對你的界面感覺良好。拿下面的滑出式菜單舉個例子:
這是 Nash Vail (@nashvail)在CodePen上創建的Pen nJial。
點擊菜單欄會從左邊跳出菜單,但是這個出現的動作顯得很生硬。CSS表的第51行將這個動畫的transition-timing-function
設置為linear
。這個動畫效果顯然可以優化。讓我們使用cubic-bezier 來創建一個私人定制的定時功能。
如果你讀到了這里,我猜你一定是個設計師或者開發人員,又或者兩者兼是,因此,你對三次貝塞爾曲線一定不會感到陌生,很有可能至少遇到過1次。貝塞爾曲線的創造就是一個奇跡。 它們一開始是被用於計算機圖形學來繪制形狀,並且被用在Sketch和Adobe Illustrator這類工具中來繪制矢量圖形。三次Bezier曲線使用如此廣泛的原因是它們用起來非常方便:我們只需要改變4個不同點的位置,然后創造我們需要的曲線。
我們一般都會知道動畫中物體的起點和終點位置,所以可以輕易鎖定這兩個點。然后就只要找到我們需要改變速度的兩點位置。前兩個固定的點被稱為錨點,剩下的兩個又叫控制點。
截取的貝塞爾曲線的一部分。 (點開看大圖)
正如你所知,cubic-bezier
需要四個參數(n1, n2, n3, n4
)來定制 transition-timing-function
。這四個參數代表的是兩個控制點的位置: n1, n2
表示第一個控制點的x、y坐標點,n3, n4
則表示第二個控制點的x、y坐標點。改變控制點的位置會使曲線的形狀發生變化,n1, n2, n3, n4
全部或部分改變時我們的動畫效果也會不一樣。 舉個例子,下面是傳入參數為cubic-bezier(.14, .78, .89, .35)
時的結果:
傳入參數為(.14, .78, .89, .35)
的三次方貝塞爾曲線。(點開看大圖)
這些隱藏在看似簡單的曲線背后的數學知識着實令人着迷。
好了,好了,讓我們回想一下初衷:我們想借助三次方貝塞爾曲線來定制過渡時間功能的函數
。我們需要的是能夠快速滑出,然后速度逐漸慢下來,最后停止的菜單:
調整后的三次貝塞爾曲線。 (點開看大圖)
看上去很不錯。這個動畫會開始很快然后逐漸慢下來,而不是全程都以一個恆定的速度移動。我只是簡單地從上文中復制cubic-bezier(.05, .69, .14, 1)
然后拿它替換了linear
。
這是Nash Vail (@nashvail)在CodePen發布的Pen nJial。
看到差別了吧?第二個版本看上去自然了很多,顯得更有吸引力。試想,如果你的頁面中每個動畫都有一個自然定時功能,那將是有多贊啊?
由此可見,運動曲線一點都不復雜,它們理解、使用起來都非常簡單。借助它們,你可以將你的UI頁面提升一個檔次。
我希望你已經明白了運動曲線的工作原理。如果你在使用運動曲線的過程中遇到了一些問題,或者你還根本沒有用過它們,目前對你而言,讓它們照你的意願創造漂亮的動畫,應該都是很簡單的。畢竟,動畫效果至關重要。
(完)