為什麼要制作動畫?
現在的營銷活動,用一個很簡單的圖檔去吸引消費者已經遠遠不夠。想讓消費者創造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%的時間。是以在做一個項目時,整個時間的比例非常不協調,同時也造成前端的返工比較嚴重。效率非常低,成本卻非常非常高。
現在開發動畫會借助整個工程體系的能力,比如視覺通過某一類編輯器,這些動畫編輯器需要遵循規範的結構描述語言,就是一段結構化資料,然後用播放器把結構化描述語言播放出來。這時,最簡單的動畫根本不需要業務開發,設計師隻要完成動畫的設計稿,一連串的系列都不需要前端介入。最終的傳遞其實就是從視覺開發完以後,直接用指令變成一個結構化的描述語言,最後把它釋出到線上的播放器就可以了。假如有一些業務邏輯,這時基于結構描述語言,把它轉換成業務描述語言。二者可以互相轉換,當通過編輯器導出結構化描述語言以後,把它變成業務描述語言;在其之上添加一些業務邏輯,最後再轉換成結構描述語言,讓播放器播放。最後會發現,前端能夠通過這樣的開發方式,可以不參與動畫本身制作,隻關心業務,整個動畫周期幾乎可以并行。