H5動畫開發快車道 - AnimateCC與createjs開發實踐


前言

以往做一些H5的運營項目,都是動畫設計師使用Animate cc(原來的Flash)先設計好動畫原型,然后交給我們UI開發來實現。做過動畫開發的童鞋都知道動畫開發都是比較耗費時間精力的,而且還要高質量的還原動畫設計師設計好的動畫,來回溝通成本也非常高。

那有沒有一種高效的方法來改善這種流程,提高開發效率的同時還能完成高品質的動畫呢?

經過一段時間的摸索,發現AnimateCC(就是原來的Flash)可以導出canvas動畫,而且是基於createjs這個開發輕量級游戲的js庫的,非常適合用來做移動端的一些h5動畫。不僅縮短制作動畫所需要的時間。同時它也是一個可視化的IDE,不需要編寫代碼就可以完成高品質的動畫效果;還可以通過Javascript,為動畫效果添加交互性。

比如下面這一頁動畫,如果使用傳統的html css3的動畫開發或者是canvas方式來硬寫代碼來實現,切圖加上動畫開發沒有一天應該是搞不定的;而使用AnimateCC導出配合自己寫一點點代碼,一兩個小時就可以搞定。

 

 

一些需要了解的概念

開始之前先來了解下Animate CC中做動畫的概念。

幀頻

是指每秒鍾放映或顯示的幀或圖像的數量,這個數值設置越大,動畫越快,但同時也是性能消耗大戶,一般設置24幀就可以了。

圖形與影片剪輯

我們可以將單獨的動畫,放到一個獨立的影片剪輯里,這樣可以更好的控制動畫。幾個獨立的剪片剪輯,可以組成一個完整的動畫。

當我們把圖片從資源庫拖到舞台時,它這個時候,只是普通的位圖,並不能做補幀動畫,所以我們必須把它轉換成元件。

圖形由矢量圖或者是位圖組成。

影片剪輯包含在動畫影片中的影片片段,有自己的時間軸和屬性。具有交互性,是用途最廣、功能最多的部分。

時間軸

時間軸是我們創作動畫時使用層和幀組織和控制動畫內容的窗口,層和幀中的內容隨時間的改變而發生變化,從而產生了動畫。時間軸主要由層、幀和播放頭組成。

Createjs

CreateJS為CreateJS庫,可以說是一款為HTML5游戲開發的引擎。目前被Adobe整合到Animate CC中,作為導出canvas動畫的基礎javascript庫。

它是一款為HTML5游戲開發的引擎,包含:

EaselJS:用於 Sprites、動畫、位圖的繪制,交互體驗(包含多點觸控)功能。

TweenJS:補間動畫”引擎

SoundJS:音頻播放引擎

PrloadJS:資源預加載

具體的文檔和Demo介紹以及API的使用方法,可以通過官網來了解:http://createjs.com/docs

怎么快速導出canvas動畫?

一般動畫設計給我們都是單個的使用Animate CC導出的fla源文件,就以我上面說的demo為例,長這樣:

 

 

拿到之后我們需要做一點點整理工作,先在Animate CC里面建立一個影片剪輯元件:

 

 

建好之后在Animate CC中的庫面板中就會生成剛剛建好的影片剪輯元件,點擊剛剛建好影片剪輯元件鏈接的欄目就會變成可編輯的狀態,然后取個名字,比如我這里取名為view1:

 

 

然后雙擊這個元件,時間軸里面是空白的,這個時候需要做的事情就是打開動畫設計師給我們的fla源文件,復制時間軸上所有的圖層粘貼到剛剛新建的影片剪輯里時間軸里。

這樣我們這個叫page1的影片剪輯就包含了這一頁的所有動畫,想一想如果你是要做有5頁游動畫的h5項目,就單獨把每一頁的動畫放到對應的影片剪輯里。這幾個單獨的影片剪輯就組成了一個完整的動畫。

做完這一步整理工作后,就可以點擊導出了。

 

 

它會直接把資源導出到你當前fla文件所在的目錄:

 

 

images -> 動畫所用的圖片資源
1.hmt -> html文件
1.js -> canvas所需要的圖形全部轉成canvas繪制的元件庫

打開導出的js文件,可以看到剛剛在影片剪輯里做的類鏈接已經在js生成了一個view1的方法在里頭:

 

 

然后可以發現在導出來的html文件里中混合了js代碼,我們可以新建一個main.js文件把html文件中的js代碼放進去,專門用來控制動畫的播放以及一些交互邏輯的編寫,整理代碼如下(詳細的說明有寫注釋):

html:

  1.  

  2.  

  3.  

  4. <> charset='UTF-8'>

  5. <> name='viewport' content='width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no'>

  6. 1

  7. <> type='text/css'>

  8. body {

  9. overflow:hidden;

  10. }

  11.  

  12.  

  13. <> onload='init();' style='margin:0px;'>

  14. <> id='canvas' width='750' height='1206'>

  15.  

  16.  

  17.  

  18.  

  19.  

  20.  

接下來只要把js中對應的兩行代碼修改為下面這兩句代碼就可以運行我們的動畫:

  1. var view1;

  2. view1= new lib.view();

  3. stage.addChild(view);

  4.  

瀏覽器上就可以顯示出剛才在animate cc里面經過類鏈接的影片剪輯的動畫。

但是有時候有些額外的對象或者方法是需要放在view1里面的,那怎么辦呢? 我們新建一個View1的類把animate cc里的view1給復合進去。

  1. //view1

  2. (function() {

  3.    'use strict';

  4.    function View1(){

  5.        this.Container_constructor();

  6.  

  7.        this.back = new lib.view1();

  8.        this.addChild(this.back);

  9.        this.show = function (){

  10.  

  11.            //這里可以寫額外的方法

  12.        }

  13.        //this.con = new createjs.Container() 這里可以是額外處理的對象

  14.    }

  15.    var p = createjs.extend(View1,createjs.Container);

  16.    cls.View1 = createjs.promote(View1, 'Container');

  17. }());

  18.  

然后創建這個類把它放到舞台上就可以了:

js代碼:

  1. view = new cls.View();

  2. stage.addChild(view);

最后js代碼整理如下,相關代碼已經有詳細的注釋:

  1. // 定義一些需要用到的變量

  2. var canvas, stage, exportRoot, cls={};

  3. // model來專門處理接收事件,記得要是EventDispatcher類

  4. model = new createjs.EventDispatcher();

  5. stageWidth =  document.documentElement.clientWidth;

  6. stageHeight = document.documentElement.clientHeight;

  7. stageScale = stageWidth/(750/2);

  8. canvas = document.getElementById('canvas');

  9. if(stageWidth/stageHeight > 0.665)

  10. {

  11.    stageScale = stageHeight/(1206/2);

  12. }

  13. else

  14. {

  15.    stageScale = stageWidth/(750/2);

  16. }

  17. canvas.style.width = 750/2*stageScale + 'px';

  18. canvas.style.height = 1206/2*stageScale + 'px';

  19. function init() {

  20. canvas = document.getElementById('canvas');

  21. images = images||{};

  22.       // LoadQueue是一個預加載類,可以把需要加載的資源提前加載,基本支持大多數的文件預加載。

  23.       //我這里主要處理了它的2個事件,fileload,complete。

  24.      

  25. var loader = new createjs.LoadQueue(false);  //這里一共可以是3個參數 第一個是是否用XHR模式加載 第二個是基礎路徑  第三個是跨域

  26. loader.addEventListener('fileload', handleFileLoad);

  27. loader.addEventListener('complete', handleComplete);

  28. loader.loadManifest(lib.properties.manifest);

  29. }

  30. function handleFileLoad(evt) {

  31.    //這是單個文件加載完成的事件,把它保存到一個地方之后可以直接拿來創建對象

  32. if (evt.item.type == 'image') { images[evt.item.id] = evt.result; }

  33. }

  34. function handleComplete(evt) {

  35. var queue = evt.target;

  36. var ssMetadata = lib.ssMetadata;

  37. for(i=0; issMetadata.length; i++) {

  38. ss[ssMetadata[i].name] = new createjs.SpriteSheet( {'images': [queue.getResult(ssMetadata[i].name)], 'frames': ssMetadata[i].frames} )

  39. }

  40. view1 = new cls.View1();

  41. stage = new createjs.Stage(canvas);  //獲取舞台  Stage是我們的舞台類,可以理解為所有canvas內部對象的總容器或者說是根顯示對象。

  42. stage.addChild(view1); //將容器放在舞台上

  43.  

  44. model.addEventListener('complete',function (){

  45.        alert('complete');

  46.    })

  47.    //Ticker是一個計時類,不過他是每過一幀觸發一次的,也就是說跟時間其實沒關系(因為幀頻是會波動的)。

  48.    // createjs.Ticker.setFPS();和createjs.Ticker.addEventListener('tick', stageBreakHandler);是必須要加的,stageBreakHandler里面放的是刷新舞台的方法,因為createjs需要不停的刷新舞台來刷新動畫,也就是一個重繪的過程。 平時也可以拿Ticker類做動畫。

  49. fnStartAnimation = function() {

  50. createjs.Ticker.setFPS(lib.properties.fps);

  51. createjs.Ticker.addEventListener('tick', stageBreakHandler);

  52. }    

  53. fnStartAnimation();

  54. }

  55.  

  56. function stageBreakHandler(event)

  57. {

  58.    if(stageWidth!=document.documentElement.clientWidth||stageHeight!= document.documentElement.clientHeight)

  59.    {

  60.        stageWidth =  document.documentElement.clientWidth;

  61.        stageHeight = document.documentElement.clientHeight;

  62.        if(stageWidth/stageHeight > 0.665)

  63.        {

  64.            stageScale = stageHeight/(1206/2);

  65.        }

  66.        else

  67.        {

  68.            stageScale = stageWidth/(750/2);

  69.        }

  70.  

  71.        canvas.style.width = 750/2*stageScale + 'px';

  72.        canvas.style.height = 1206/2*stageScale + 'px';

  73.    }

  74.    stage.update();

  75. }

  76.  

  77. //view1

  78. (function() {

  79.    'use strict';

  80.    function View1(){

  81.        this.Container_constructor();

  82.        this.back = new lib.view1();

  83.        this.addChild(this.back);

  84.    }

  85.    var p = createjs.extend(View1,createjs.Container);

  86.    cls.View1 = createjs.promote(View1, 'Container');

  87. }());

一個動畫效果就完成,當然剛開始的時候可能要花點時間來熟悉。一旦熟悉這個套路后,后面就會越發越熟練了。

比如下面這個小的h5動畫,使用上面的animate cc和createjs兩天就可以搞定:

 

怎么來做交互反饋

像我們一般做這些運營項目,都會和用戶發生些交互動作或者是監聽頁面的動畫事件來做進一步反饋,這個是還怎么辦呢?

這里有一個小訣竅,我們可以在幀上加上dispatchEvent,來告知程序動畫結束了,或者播放到哪個關鍵地方了。
比如這里我們在動畫的最后一幀上加上:

  1. this.stop();

  2. if(model) model.dispatchEvent('complete');

 

 

然后在js上新建一個model來專門處理接收事件,記得要是EventDispatcher類:

  1. model = new createjs.EventDispatcher();

然后在代碼中監聽就可以了:

  1. model.addEventListener('complete',function (){

  2.        alert('complete');

  3. })

在動畫結束的時候就會監聽到complete事件了:

 

 

雪碧圖功能

如果碰到圖片很多的項目怎么辦呢?Animate CC也支持導出雪碧圖的功能,在發布之前設置下就可以了:

 

 

這里要注意的是在選擇的時候選擇兩者兼有,這樣就會把jpg和png格式分別導出;png品質選擇32位的就可以了。

 

 

左邊是沒有選擇雪碧圖的,右邊是選擇導出雪碧圖的,圖片數量瞬間少了很多。導出雪碧圖就是這么簡單。

性能問題

說到做動畫性能是繞不開的話題,同樣在使用fla導出canvas動畫的時候也會碰到性能問題,這里總結下遇到的性能問題,一般都是在用Animate CC做動畫的時候可以規避掉,總結一句話就是:

減少矢量 減少影片剪輯(movie clip) 減少嵌套  減少濾鏡特效。

詳情如下:

1、嵌套規范

在使用CC設計動畫效果時,盡量不要太多的嵌套,比如:影片剪輯里面再嵌套影片剪輯或者是幀里面再嵌套其它幀。

2、濾鏡和動畫規范

不要使用濾鏡特效比如(陰影濾鏡和發光濾鏡)來做動畫,因為這樣會非常耗費性能,在移動端上性能不可控。

可以使用逐幀圖片來代替相關濾鏡特效來實現動畫效果。比如下面效果里面的花瓣飄落和螢火蟲的效果可以使用逐幀圖片來做。

3、素材規范

少用矢量多用位圖,Text shape都算矢量(如果是用 flashCC或者animateCC做的,在里面就直接把字和矢量圖轉成位圖)。

使用Animate CC做動畫效果的基本知識就介紹到這了,有什么問題可以留言一起交流交流。

各位設計的小伙伴們,可以嘗試下使用Animate CC來做動畫效果,特別是H5類型的動效。不僅高效還可以高質的還原出設計師的動畫效果。

使用Animate CC來設計動效,你好,我好,大家都好!

 

 

感謝你的閱讀,本文由 騰訊ISUX 版權所有,轉載時請注明出處,違者必究,謝謝你的合作。

注明出處格式:騰訊ISUX (https://isux.tencent.com/card-design-thinking.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM