從手機端 H5 製作來看 WEB 動畫的術與道

ES2049發表於2019-03-05

我們在微信朋友圈裡經常看到很多人分享 H5 的連結,有的科技感十足,有的展示炫目,有的非常有創意,各大公司也把H5作為他們品牌傳播,活動預熱的很好方式。企業商戶對於這種方式也很有好感,從而導致了 H5 製作行業湧進大批從業者。這幾年做過幾十個 H5 ,每一次都在思考動畫與技術的關係,於是記錄下來。

H5

當你拿到一個 H5 製作的需求的時候,你需要首先明確需求的目的是什麼?按照目的大概可以分為活動營銷,產品宣傳,會議邀請,品牌推廣,企業招聘等。不同類別的 H5 有其自身的特點,但找準業務方的目的,就能抓住主題而不會跑題了。 接下來就是圍繞這個主題思考創意。創意很多是來自於營銷策略,方法以及對於人性的把握,這些偏軟性的思考方式,我們先不討論,作為一個程式設計師,我首先想到的就是怎麼通過技術帶來創意。

在此之前,我們先來看看製作一款 H5 有哪些「術」。

一個需求只要處在瘋狂的爆炸成長期,行業看到了其巨大的市場,就一定會盡量的降低成本和使用門檻,來儘快的吸引使用者,於是一些低門檻的h5製作平臺相繼出現,不懂程式碼的人也可以來玩玩,如果你有一定的設計思維和作圖能力,也能做出非常好看的H5作品了。綜合我的使用經驗,大概總結如下:

國內比較成熟的 H5 製作平臺有:

  • 兔展:設計感和創意感最強的平臺,但是製作相對複雜,需要設計基礎。
  • 易企秀:老牌的 H5 製作平臺,不斷迭代,有大量案例,使用別人做好的 H5 需要付費。生態圈還不錯。
  • 初頁:手機 APP,手機端快速製作 H5 。適合個人使用者快速製作。
  • Epub360 意派:面向設計師,提供了很多創意的設計元素和案例。

從手機端 H5 製作來看 WEB 動畫的術與道

易企秀 H5 製作後臺

這些平臺都可以讓使用者通過簡單的拖拽來製作一個精美的 H5 ,這種打包預設好一些動畫模式的方式,非常像我們前端開發中的元件化思維,他們將元素和資料分離,用資料模型來描述元素的位置和運動,同時開發出一套動畫引擎,只要將模型資料輸入,就能呈現出精美的動畫。

我覺得這些平臺非常合適的 WEB 動畫的學習,深入探究其動畫的實現思路,可以讓我們快速的梳理出「動畫」和「 WEB 動畫技術」。

WEB 動畫技術

你在做動畫的時候,真的理解是什麼是動畫嗎?維基百科告訴我們,動畫是由一幀幀的靜態圖片按照一定的順序,一定的速度播放而產生的,是一種障眼法。然而我並不想這麼生硬的去理解他,對於真實世界的觀察或許能給我們更為真切的體感。我們想一想人在運動的時候,我們肢體動作包含哪些動畫元素呢?

簡單動畫

從手機端 H5 製作來看 WEB 動畫的術與道

  • 移動 (水平,垂直)
  • 旋轉
  • 縮放 (放大,縮小)
  • 樣式屬性

身體的位移,骨骼的旋轉,瞳孔的縮放,這些都是最基本的運動方式,樣式的變化,則是元素自身屬性的變化,例如顏色,邊框,背景等,這寫也是大部分動畫程式設計最基本的要素。你完全可以使用 CSS3 來實現他。我們知道一個動畫要包含,元素變化。CSS3 基於 DOM 元素,藉助動畫三劍客 Transition (過渡) Transform(變形) Translate (移動),實現變化。有一個非常好用的 CSS 動畫庫 —— Animate.css ,他預設了很多實用的動畫模版,你只要在 DOM 節點上新增響應的 class 就可以了。

他們即簡單又複雜,複雜在於這些運動的方式和速度、時間的結合誕生出了速度曲線,然而大自然中大多數的速度曲線來自於重力加速度 G ,由於他的存在,物體的運動不像真空中那種勻速直線的單調乏味。而充滿了生機。

尤其是當你在做動畫的時候,為什麼你做出的動畫顯得非常的生硬,讓人看著不舒服,其實人早已習慣了大自然的動畫方式,人對每一幀動畫都有穩定的預期,當你的動畫與現實物體的運動脫節,就會變得生硬。

基於上述簡單動畫催生了一種人體動畫的形式---叫做「骨骼動畫」。

複雜動畫

骨骼動畫的製作,屬於一種相對複雜的動畫形式,我們通過程式碼一點一點的寫會非常困難,幸運的是業界早就有了成熟的工具幫助你省去了複雜的編碼過程,讓你只去關注創作本身。有兩款比較著名的 2D 骨骼動畫製作軟體:Spine 和 DragonBones 。

從手機端 H5 製作來看 WEB 動畫的術與道

DragonBones 骨骼動畫軟體操作介面

我們以 DragonBones 為例,我們發現下面的有一部分,操作欄是「時間軸」,他可以描述我們每一幀動畫的狀態,這裡其實出現了兩種與時間相關的動畫形式。

  • 逐幀動畫
  • 關鍵幀動畫

作為一個前端工程師,我們在做動畫的時候往往不會去寫每一幀的動畫的狀態,而是先去定義起始狀態和中間動畫的過渡方式,例如速度如何變化,路徑如何變化。這是一種關鍵幀動畫,在 CSS3 中我們可以用 Animation 中的Keyframes 來實現關鍵幀動畫,Keyframes 來定義關鍵幀的狀態,Animation 來定義時間和速度變化。

而對於逐幀動畫,則明顯不是 CSS3 的強項,這裡就要引出更為強大的武器 —— Canvas 了。

逐幀動畫

在 Canvas 中,動畫的元素可以由 Canvas 皮膚自定義的形狀繪製,也可以載入圖片來實現。元素的變化,則依賴 requestAnimationFrame(callback) 函式,推進時間的流逝,來重繪每一幀的畫面。在逐幀動畫領域有一個比較著名的框架,PixiJS 。

PixiJS 一直以高效能的 2D 渲染引擎著稱。Pixi 主要負責渲染畫面。可以建立豐富的互動式圖形,動畫和遊戲,而無需深入瞭解 WebGL API 或處理瀏覽器和裝置相容性的問題。與此同時,PixiJS 具有完整的 WebGL 支援,如果需要,可以無縫地回退到 HTML5 的 Canvas 。PixiJS 預設使用 WebGL 渲染,也可以通過宣告指定 Canvas 渲染,WebGL 在移動端 Android 4.4 browser 並不支援,不過可以使用 Canvas 優雅降級。

進入 Pixi 的世界,我們欣喜若狂,終於可以實現畫素級別的動畫了,Pixi 提供的強大濾鏡,也讓我們實現很多特效變得非常簡單,然而作為一個渲染引擎,他很好的做到了高效能,而忽略了易用性,學習成本比較高,API比較複雜,尤其是逐幀動畫的編碼方式似乎有點反常識,或者說寫起來並不是那麼順暢,而關鍵幀動畫似乎更符合我們的程式設計習慣,畢竟 CSS 動畫,我們爛熟於心。

那怎麼用 Canvas 實現關鍵幀動畫呢?我們為了實現某種目的,首先應該找的是方法,而方法往往已經被前人總結好,放在了你的面前,這裡我們來聊兩個框架: CreateJSGreenSock

關鍵幀動畫

當我們定義了關鍵幀和變化方式以後,演算法會幫我們計算出元素在每一幀的狀態,我們把這稱之為補間動畫。 CreateJS 和 GreenSock 都是實現補間動畫的高手。

CreateJS 和 GreenSock 都是基於 HTML5 的一套模組化的庫和工具。不僅可以實現 Canvas 動畫,也支援 DOM 動畫,DOM動畫的原理依然是基於 CSS3 的,由於 CSS 動畫三劍客並不會引起瀏覽器頁面內容的重排和重繪,甚至還可以開啟 GPU 加速,效能比直接操作 DOM 的 width、left、margin 等屬性要高的多。

其實 CSS 動畫和 Canvas 動畫的效能到底哪個更好,並不能一概而論,這個依賴於你具體使用的場景和瀏覽器型別,具體的效能比較可以看 這裡 ,而我認為促使我們選擇 Canvas 來做動畫的一個關鍵點在於兩者明顯不同的思考方式。

  • 我們把動畫的主體叫做元素,在 DOM 上,元素是按照經典的「盒子模型」做組裝和佈局的,盒子模型天然具有父子關係和相對位置。當我們實現一些區域性動畫的時候,是非常方便的。
  • Canvas 並沒有盒子的概念,他只有一個畫布標籤,而這張畫布被稱為舞臺,舞臺上任何的元素都可以自由的運動,這更像真實世界的運作方式。
  • 這兩種思考方式可能正是UI設計師和前端工程師,在工作時的差異。當我們用前端的「盒子」思維開發一個拖拽式頁面工具讓設計師來用的時候,你就天然的在要求他們用自己不熟悉的方式去思考,畫畫和設計他們只有一張畫板,他們先打上均勻的格子,然後找準方位,一氣呵成,他們在意的是整理的美觀性。

話說回來,我們來看看,關鍵幀動畫基本的實現形式是怎樣的?CreateJS 中有一個專門實現關鍵幀動畫的庫——TweenJS,而 GreenSock 中也有同樣功能的庫—— TimelineMax。

// TweenJS 的 API
createjs.Tween.get(circle, { loop: true })
  .to({ x: 400 }, 1000, createjs.Ease.getPowInOut(4))
  .to({ alpha: 0, y: 175 }, 500, createjs.Ease.getPowInOut(2))
  .to({ alpha: 0, y: 225 }, 100)
  .to({ alpha: 1, y: 200 }, 500, createjs.Ease.getPowInOut(2))
  .to({ x: 100 }, 800, createjs.Ease.getPowInOut(2));

// TimelineMax 的 API
var tl = new TimelineMax();
tl.to(element, 1, {left:100}).to(element, 1, {top:50}).to(element, 1, {opacity:0});
複製程式碼

我們可以看到,兩者 API 非常的相似,都採用了鏈式呼叫的方式,定義每一個關鍵幀和時間,以及非常關鍵的運動曲線,區別在於 TweenJS 專注單個元素的運動,TimelineMax 更關注在一個時間線上,不同元素的運動。

相比而言,對於動畫的實現上,GreenSock 借鑑了很多 Flash 的實現方式,外掛非常多,功能更全,效果更炫。其實當我們在選擇一門動畫框架的時候,切記不要貪多,在滿足需求的基礎上,深入去研究一種框架,達到熟練,才能做出更好的效果和創意。我一直認為,創新是建立在豐富的知識儲備和見識之上的自然湧現,尤其要求對技術的深度,如果一直在嘗試不同的框架,就只能不停的學習各種 API ,而忘記了動畫的本質並不是技術,而是好的創意。

當我們在實現動畫的時候,慢慢會發現,大部分的元素都是圖片,而且圖片是提前預設好的,不能更改,只能用新的圖片替換,例如當我們要實現微笑動畫的時候,需要畫兩張圖,一幅是閉著嘴的,一幅是張嘴笑的,然後逐幀播放。這樣的畫面當你有足夠多幀圖片的時候,並不會看出生硬,一旦低於 24 幀就是變得不自然了,那怎麼在不增加工作量的前提下,實現流暢的變化呢?我們將關鍵幀動畫的思維嫁接到元素自身扭曲變化上,就催生出了「柔性動畫」的概念。

柔性動畫

從手機端 H5 製作來看 WEB 動畫的術與道

從上圖可以看出,元素之間是可以相互變化的,而且非常的流暢,這樣的動畫並不需要 Canvas 這種重武器,簡單的 DOM 就可以實現,SVG 真的是一個神器,不僅在實現圖示,字型上特點鮮明,在實現柔性動畫方面也獨樹一幟。SVG 依然是 DOM ,他有自己獨有的 Animation 標籤,但也支援 CSS 的屬性,其實現動畫的本質是依賴於線條填充,線條的變化,導致填充區域的改變,從而引起形狀的變化。而線條則依賴於路徑錨點,路徑和錨點的改變,直接影響了線條的變化。

上面的案例,使用的是 GreenSock 的 SVG 動畫外掛 —— MorphSvgPlugin ,他可以實現不同 SVG 元素之間的相互轉換,過渡非常平滑。

SVG 實現的動畫比較區域性和小巧,使用範圍也比較狹窄,但是當我們實現複雜的柔性動畫,甚至遊戲的時候,就還是需要用 Canvas 來實現。

從手機端 H5 製作來看 WEB 動畫的術與道

從上圖我們可以看到龍的翅膀是一張圖片,但是可以通過圖片的區域性的扭曲和變形,來實現煽動翅膀時帶來的肌肉收縮和舒張。這樣的動畫是怎麼實現的呢?這就要引出骨骼動畫中,一個非常重要的概念:網格

這裡我們比較淺顯的討論下這個概念,要實現圖片的區域性變化,我們就要把圖片分塊,分的每一塊就稱為網格,每個網格都有自己的頂點和邊,頂點的位移會引起網格形狀的變化,形狀的變化就會帶來所附屬的圖片的變化。網格的概念是不是很像路徑和錨點,不論怎樣的技術,在實現邏輯上都大同小異,重要的不是一直盯著不同和變化的部分,而是發現那些不變的地方,才能達到觸類旁通的效果。

製作這樣的動畫並不複雜,你可以使用類似 Spine 和 DragonBones 這樣的工具,但是做動畫真的是一個體力活,你需要不斷的除錯,以求達到一種讓人看起來舒服的狀態。

總結

在大前端概念下,WEB 動畫是一個非常絢爛又深邃的領域,甚至不只侷限於前端,他更注重使用者的互動體驗,以及真實世界的虛擬化。這裡我們也只討論了這座大山的冰山一角,還有很多動畫形式需要進一步研究和思考,例如:

  • 粒子動畫
  • 特效動畫
  • 3D動畫
  • 資料視覺化動畫 ...

當我們更深入研究,就會發現,數學的重要性,審美的重要性,創意的重要性。技術只是工具,他所湧現出來的是一種對於美的追求和體驗。雖然說的不明覺厲,但是真的值得好好思考一下。

參考

文章可隨意轉載,但請保留此 原文連結

非常歡迎有激情的你加入 ES2049 Studio,簡歷請傳送至 caijun.hcj(at)alibaba-inc.com 。

相關文章