為什么要制作動畫?
現在的營銷活動,用一個很簡單的圖片去吸引消費者已經遠遠不夠。想讓消費者創造GMV,肯定需要讓消費者覺得眼前一亮或是有視覺沖擊的東西,或者在動畫過程中提供更好的引導部分,比如紅包,引導消費者去戳紅包,他們自然而然就進入到角色當中。歷年雙十一手淘動畫層出不窮,去年一些比較典型的動畫、場景,其實也是給大家展示了一次事件; 這些提供給消費者或者用戶的動畫,其實就是一個入口,讓他們知道手淘正在做某活動。
制作動畫的方式很多,以前會讓視覺設計師或動畫設計師去做一個視頻、GIF, FLASH。相對來說,這整個流程比較簡短,因為當視覺設計師產出了視頻GIF或者FLASH之后,直接把它放到網頁里,或者直接拿播放器播放就可以。但它是一個已經定好的內容,沒法根據不同用戶的交互產生一些變化。緊接著HTML5的應用越來越廣泛,可以用SVG、Canvas以及HTML5做動畫,這樣就會達到引導用戶,或者說千人千面的效果。
?
動畫有一些基本的組成要素,每一個元素有各自的特性,比如尺寸、位置、樣式、變化(比如旋轉或是縮放)等等。元素是整個動畫里最基礎的組成部分,有了元素以后,就把它交給引擎去渲染。因為元素本身是一個描述性結構,要讓引擎把元素繪制出來。引擎的概念比較廣義,可以是CSS;也可以是Canvas。有了元素以后,就需要讓動畫動起來,所以需要一個動效器。動效器用來描述元素的一系列的動作,包括元素的動畫時長,動畫是否要循環,以及緩動函數。一個動效器可作用一個元素。因為動效器的概念相對底層,因此可以基于動效器二次開發,開發一些更加接近現實、接近物理學的動畫內容。比如說粒子效果,因為其隨機性,近幾年應用非常廣泛。包括物理學上的自由落體、鐘擺、視差等等,其實都跟物理學本身有關系。可以借助動效器,再借助一定的數學公式把它變成更加復雜的一段動畫。
元素和動效器組合起來就叫動畫。動畫本身有一些特定屬性,比如動畫開始播放、結束播放,以及播放的狀態等等。有了動畫就要有時間,時間軸就應運而生。最后需要一個觸發器,其實觸發器的概念主要針對于程序開發。因為需要每一幀都觸發一下,讓時間軸跑起來,然后動畫真正地開始運作。不管是哪些工具,哪些動畫,它其實解決了幾個問題,讓元素變得簡單,讓描述動效變得簡單,讓管理動畫變得簡單,最終讓開發整個動畫變得簡單。
如何制作動畫?
?
現在簡單說一下在開發模式當中怎樣形成一個動畫。以紅包火山為例,右側的鏈路是最普通的開發動畫鏈路。首先在動畫里創建一個場景,接著把需要用到的元素添加到場景里去,再接著給這個元素綁定一個動效,也就是創建出來一個動畫,最終把動畫播放出來,就能看到紅包火山的效果。那么,每一步主要做什么呢?
?
首先創建場景,場景這個概念在動畫里不具體指某一元素或某一具體可以被繪制的內容。當有元素被添加到場景之后,才會被渲染。否則,就算創建了這個元素,它也不會被渲染。這么做是為了在動畫的整個渲染過程上節省一點成本。舉個例子,紅包火山動畫元素將近三四十個,有些動畫元素在最開始并不需要,但是在寫代碼時先創建了它,然后在需要用的時候把它渲染出來。這時需要有一個管理機制去識別哪一些元素,需要在什么時候被渲染,這就有一個場景的概念了。
?
在做紅包火山動畫的時候,把它歸為一個場景四個片斷。最開始倒計時,中間有一段火山升起,第三個是火山升起以后的火焰噴發,噴發結束,或者在噴發的同時,有紅包噴發。整個紅包火山就是這么一個場景。
?
有了場景以后,需要添加元素。首先讓元素有一個形狀,一般來說,元素的形狀可以簡單地歸類為矩形、圓形、橢圓形、三角形。因為字體文本特殊一點,所以會單獨拿出來。另外還有組,幾個元素合在一起叫做一個組。創建完一個元素以后,用元素本身的特性,如樣式、位置、變換等去描述元素。實際上,現在手淘應用到的大多數動畫,基本上都是一張背景圖片。因為設計出來的背景圖片本身比較符合手淘的規范。現在很多動畫主要借助矩形元素,并在矩形元素里貼入圖片,然后把這些元素組合起來,最終變成一個動畫。其他用的比較多的還有SVG動畫。SVG在近幾年流行程度越來越高,因為首先它在手機端的兼容性非常好;其次它可以做一些其他動畫沒法做到的效果,比如說從圓形變成三角形;或者通過比較復雜的路徑,產生一些意想不到的變化。相對來說,SVG的能力更強大。不過目前要完成一個簡單的動畫,不需要SVG這種高級的動畫效果。
?
在來看火山動畫里的元素組成。火山主體是一個組,由下面四種元素組成:一是火山的后景,其余是三個火山的前景。把整個火山分成四個單獨的元素,并且把這四個單獨的元素變成了一個組。
?
在這里穿插一個知識,動畫世界中的坐標系統。元素的位置就是動畫里面的坐標。如上圖,灰色框是個畫布,把它認為手機屏幕,這時手機屏幕或者畫布的中心點是坐標的原點,就是(0,0)位置。每一個元素也有其坐標,叫元素坐標。元素的坐標原點也是元素中心點(0,0)。最常用的坐標系是笛卡爾坐標系(右手坐標系),如上圖所示意的,右手大拇指指向X軸,食指指向Y軸,中指指向的位置是Z軸,這些都指向X、Y軸的正方向,是標準的右手坐標系。
?
但是前端在寫頁面時,CSS里是左手坐標系。這和動畫里經常遇到的坐標系不一樣,所以需要熟悉不同的坐標系。比如,CSS里面X軸位移、Y軸位移一個,在動畫里,X軸和Y軸的位移其實相反。有一個特別容易被忽略的是旋轉,CSS里的旋轉是順時針,動畫里定義的旋轉是逆時針。所以,這兩者坐標的差異,需要開發時做一個簡單的轉換,從CSS的坐標系轉換到動畫坐標系。
?
下一步要給動畫創建動效,一個元素綁定一個動效以后才真正成為一個動畫。動效本身會有一些具體內容,比如,當創建元素時,它的狀態其實已經創建好了。這張圖片多大,或者元素多大,還有動效的時長、延伸、晃動,或者循環的方式等等,都根據W3C的標準定義。最終,通過元素以及動效變成一個動畫。
?
那么為什么把火山的整體變成一個組呢?其實火山上升時,有一個抖動效果,且前面三塊巖石和火山的上升速度不一樣。為達到這種效果,在這里做了一個簡單的處理,讓整個火山上升,同時又讓前景的三塊石頭上升,把這個四個動畫組合起來,達到了這樣的效果。一開始石頭不在一起,最終把所有石頭拼在一起,拼成火山。把這四個元素變成一個組,讓組抖動,組里面的元素也會跟著抖動。這樣處理的目的是,優化性能。如果對很多元素做不同的效果,相較于對一個組做一效果,性能會變差。
?
把動效簡單地分解一下,其實設置比較簡單,包括樣式、時間,以及循環等,這是動效本身的一些組成部分。
?
這是單個動效,有時候需要把多個動效組合在一起。比如說紅包火山,一個沿Y軸移動的動效,一個沿X軸抖動的動效。把這兩個動畫組合在一起,就變成一個復合動畫。如果再加一個Z軸的旋轉,動畫會更復雜。其實每個動效可以單獨處理,當組合在一起,可以做很多不同的事情。
?
有了動畫,接下去就簡單了,就是播放場景里的動畫,這也是整條做動畫鏈路最簡單一個方式。
?
如何管理動畫?
通過創建場景、創建元素、創建動畫、播放動畫,完成了一個簡短的動畫。但是當做一個復雜項目,這一種方式遠遠不夠。因為動畫有先后順序,有重疊時間,這時需要讓每一段動畫在合適的時間播放,所以需要一個智能的控制系統,去管理每一個動畫。
?
紅包火山升起噴發的動畫做了四件事情:火山升起用時一秒;火山升起以后,火焰噴發用了0.4秒;火山升起以后同時巖漿往下流,也就是說,火焰噴發和巖漿流動同時開始,但是都在火山升起以后才執行;當火焰噴發以后,紅包才開始噴發,巖漿其實一直在流動。這幾段動畫有一個先后順序,也有重疊關系。
?
這里先簡單說一下,CCS在處理這些動畫時的短板,如火山升起用了1秒,緊接著讓火焰柱噴發,這時,火焰柱開始噴發的時間在CSS技術里有一個delay屬性,比如說延遲1秒鐘,然后再讓火焰柱噴發;相應地,巖漿流動也是同樣的道理,也會延遲1秒鐘,然后讓巖漿流動。火山升起的時間,加上火焰柱噴的時間,這么長的延遲以后再分發紅包,這種技術方案雖然解決了問題,但是沒能提高效率。
?
所以在動畫體系里,提出時間軸的概念。創建時間軸,并在加入一個動畫,給該動畫兩個參數,即開始時間和結束時間。當然,這兩個時間不僅僅可以用絕對時間值,還可以是狀態碼。正常情況下,不會關心火山升起用了多久,只關心火山升起結束的狀態。相應地,火山噴發也有一個開始時間和結束時間,但后續的動畫并不關心這個時間,只要知道火焰噴發結束這個狀態就可以了,再繼續下一個動畫就可以了。CSS本身沒有這樣的能力,而JS就可以駕輕就熟。
?
如何擴展動畫?
很多動畫會處理成圖片位移加上元素位移的形式。
?
比如精靈動畫也叫雪碧圖動畫,它是很多張圖片(或一張圖片展示不同的位置)不斷地切換輪播產生的效果,是最常用的一種手段。另外一個是路徑動畫,位移最直觀的是一條直線,從X點到Y點;如果移動軌跡是一條很復雜的曲線,就要建立路徑。路徑在動畫里非常普遍,要通過動效做出來復雜的動畫,就要用到現實或物理中一些抽象的能力。
?
精靈動畫可以提取出來幾個關鍵詞:一是精靈圖片的地址,如上所述,這是很多張圖片的拼接;二是每一幀精靈圖片的尺寸;三還要知道這張圖里一共有多少幀精靈圖片;四是精靈圖片播放的序列,因為在很多應用場景里,設計師提供了一組精靈圖片,可能其中的某一個區段或者某幾幀圖片要重復利用,循環播放,這時必須要知道在播放整個動畫時,幀序列是什么;最后就是最基本的播放參數,比如時長、延時等等。把這些內容抽象出來以后,通過插件的形式轉換動效代碼,就達到了最簡單的擴展動畫的需求。
?
路徑動畫其實一樣,一般很多種方式提供路徑。路徑其實就是描述了一個不規則的曲線,可能是弧線、貝塞爾曲線、離散曲線等,只要給定一個路徑,就可以經過參數配置,在每一個時間點計算該路徑上的某一點在哪,再讓該元素運動到路徑的那點就可以了。擴展出的路徑動畫還有一些特定的效果,比如物體在移動時是否根據曲線的切線或法線進行旋轉等等。
?
如何改進開發模式?
?整個項目來看,開發動畫只是其中的一小部分,只動用了前端這一個技術層面,但是做整個項目的時候,有PD、視覺、運營、市場、前端技術等等。所以真的要完成一個動畫,開發模式應該怎樣做呢?
?
手淘早期開發動畫的時候,簡單粗暴,視覺提供設計稿,可能是一個視頻、GIF或FLASH,前端用眼睛識別這個動畫,用CSS或其他技術還原。視覺會定期檢查說動畫跑得不對,少兩個象素等。這樣,每一個動畫開發下來,拋開業務層面,光開發動畫就可能會花掉整個項目周期70%-80%的時間。所以在做一個項目時,整個時間的比例非常不協調,同時也造成前端的返工比較嚴重。效率非常低,成本卻非常非常高。
?
現在開發動畫會借助整個工程體系的能力,比如視覺通過某一類編輯器,這些動畫編輯器需要遵循規范的結構描述語言,就是一段結構化數據,然后用播放器把結構化描述語言播放出來。這時,最簡單的動畫根本不需要業務開發,設計師只要完成動畫的設計稿,一連串的系列都不需要前端介入。最終的交付其實就是從視覺開發完以后,直接用命令變成一個結構化的描述語言,最后把它發布到線上的播放器就可以了。假如有一些業務邏輯,這時基于結構描述語言,把它轉換成業務描述語言。二者可以互相轉換,當通過編輯器導出結構化描述語言以后,把它變成業務描述語言;在其之上添加一些業務邏輯,最后再轉換成結構描述語言,讓播放器播放。最后會發現,前端能夠通過這樣的開發方式,可以不參與動畫本身制作,只關心業務,整個動畫周期幾乎可以并行。