介紹篇:
貝塞爾曲線,法國數學家Pierre Bézier製造。
一種繪製曲線的方法,配有詳細的計算公式,按照這樣的公式繪製出來的曲線是為貝塞爾曲線。
其在計算機圖形中的應用相當廣泛,幾乎有曲線的地方,就少不了它的身影,如在Photoshop,Flash,CorelDRAW中的使用。
常見貝塞爾曲線示例圖:
一階貝塞爾曲線(線段)
二階貝塞爾曲線(拋物線)
三階貝塞爾曲線
其在CSS動畫中的使用,簡單的說,就是在動畫的運動過程中,控制速率的變化。
進階篇:
CSS動畫中使用的是三階曲線,如下圖所示,三階曲線共有P0,P1,P2,P3四個節點,其中P0是起點、P3是終點,P1和P2是控制點。同時CSS中使用的曲線,有些特殊,它固定了起點P0(0,0)和終點P3(1,1),僅有控制點可以移動。移動控制點可以改變曲線的曲率(彎曲的程度),通過曲率的變化反映出速率的變化,應用於動畫之中。
之後我們來看下曲率對應速率變化的規律。X軸和Y軸,我們理解為時間軸和距離變化軸,那麼單位時間內,距離變化的多少,反應出來的就是速度的快慢。
下圖中,X軸的切分是均等的,同時虛線矩形內,x1對應的y1、x2對應的y2,也是相等的,那麼認為起點到終點是勻速變化的。
下圖中,X軸的切分是均等的,同時虛線矩形內,x1對應的y1 大於 x2對應的y2,那麼認為起點到終點的運動過程中,速度是先快後慢的。
這兩種曲線反應到具體的動畫之中的效果如下。
CSS動畫中,使用貝塞爾曲線作為值的屬性有兩個,transition-timing-function,animation-timing-function,格式為cubic-bezier(P1x,P1y,P2x,P2y),實際應用中的程式碼例項 transition: all 3.0s cubic-bezier(0.75, 0.25, 0.25, 0.75)。
可能你大多看到的是,ease,linear,ease-in-out 這樣的屬性值,其實它們也是貝塞爾曲線值,只不過是官方預定義的,以簡化明瞭的名稱,替代了複雜的數值書寫方式。
以下是一些預定義名稱對應的曲線值:
ease: cubic-bezier(0.25, 0.1, 0.25, 1.0)
linear: cubic-bezier(0.0, 0.0, 1.0, 1.0)
ease-in: cubic-bezier(0.42, 0, 1.0, 1.0)
ease-out: cubic-bezier(0, 0, 0.58, 1.0)
ease-in-out: cubic-bezier(0.42, 0, 0.58, 1.0)
深入篇:
1)邊界和峰值
前面提到過,CSS中的曲線是固定了起點P0(0,0)和終點P3(1,1)的,那麼可直觀的認為 X 和 Y 的取值範圍是0 – 1。但實際使用中,僅 Y 的取值是允許超出範圍的。
如果 X 的取值超出範圍,瀏覽器會認為屬性值非法,而無法正常執行動畫。如果 Y 取值超出範圍,因為 Y 表示的是距離,所以表示出來就是運動距離超出邊界或者運動距離反向變小,然後再繼續運動到終點,想象出來了嗎,是的,這是回彈效果。
峰值表示速度達到最大或最小,很短暫的停留後,再降速或加速到達終點。因為僅有兩個控制點,所以會有一個或者兩個峰值,表示有一個或者兩個速度轉折到過程。可以利用峰值,更好的實現動畫來表現自己要傳達的引導意識。
2)視差
鑑於更好的理解,上文都是以運動距離屬性,來形象的表達動畫。貝塞爾曲線表示的是速率,那麼基本上可以連續變化的屬性,都可以應用,而不僅僅是距離,比如顏色,透明度,尺寸,縮放,翻轉等等。如果再加上不同的動畫延遲時間,不同的動畫運動持續時間,就會產生酷炫的視差效果。
3)案例
仔細看幾遍就會發現,其實五個點的動畫是一樣的,僅僅是作用了不同的延遲時間,就產生了很高大上的視覺效果。那我們現在拆分出單個點的動畫,再來觀察,看下圖:
可以觀察到以下幾個細節:
1. 圓點起初是不可見的,動畫的最後是漸隱的,可以用opacity實現。
2. 圓點的運動軌跡是圓周運動,可以用rotate實現。
3. 在速度上,可以分為幾個階段,先由快到慢,然後勻速,然後慢到快再到慢,然後勻速,最後再由快到慢。
OK,可以下手寫程式碼了,我們依照速度的變化規律,把整個動畫劃分為多個階段,為每個階段寫上當前的終點樣式,包括旋轉角度、透明度值。現在動畫已經可以執行了,只是不夠酷,因為CSS中貝塞爾曲線的預設值,即是 linear: cubic-bezier(0.0, 0.0, 1.0, 1.0),[勻速],所以動畫的每個階段都是勻速變化的。
現在我們為每個階段加上,已經調出的貝塞爾曲線取值,再看下效果,是不是和最終效果一樣了。
最終程式碼如下,大家可以藉助文章最後給出的工具,自己多多試試,然後在程式碼裡改成自己的貝塞爾曲線,看看效果吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.loading { position : relative; display : inline-block; } .loading .dot { position: absolute; opacity : 0; width: 64px; height: 64px; transform: rotate(225deg); animation-name: loading; animation-iteration-count: infinite; animation-duration: 5.28s; } .loading .dot:after { content : ""; position : absolute; width : 6px; height : 6px; border-radius : 50%; background : #000; } .loading .dot:nth-child(2) { animation-delay : .23s; } .loading .dot:nth-child(3) { animation-delay : .46s; } .loading .dot:nth-child(4) { animation-delay : .69s; } .loading .dot:nth-child(5) { animation-delay : .92s; } @keyframes loading { 0% { transform : rotate(225deg); opacity : 1; animation-timing-function : cubic-bezier(0, 0, 0.58, 1.0); } 8% { transform : rotate(345deg); animation-timing-function : cubic-bezier(0.0, 0.0, 1.0, 1.0); } 30% { transform : rotate(455deg); animation-timing-function : cubic-bezier(0.42, 0, 0.58, 1.0); } 40% { transform : rotate(690deg); animation-timing-function : cubic-bezier(0.0, 0.0, 1.0, 1.0); } 60% { transform : rotate(815deg); opacity : 1; animation-timing-function : cubic-bezier(0, 0, 0.58, 1.0); } 75% { transform : rotate(965deg); animation-timing-function : cubic-bezier(0, 0, 0.58, 1.0); } 76% { opacity : 0; } 100% { opacity : 0; } } |
備註:以下是兩個可以即時除錯曲線的頁面應用