首先介紹phaser和animate.cssjavascript
animate.css相信大部分作前端的同窗都用過,是一款強大的css動畫庫,裏面有上百種經常使用小動效。簡單的加一個類名就可讓咱們寫的頁面變得生動有趣起來。是由css的keyframes來實現的。css
phaser是一款js遊戲引擎,基於canvas和webgl。內置各類功能,好比精靈,spine,音視頻,dragonBones,物理引擎,粒子效果等等。不向cocos,白鷺等是一個大生態全家桶,phaser很靈活,很容易插入到現有項目中。我以前深刻使用過一段時間,怎麼碩呢,若是你是我的玩票性質想寫點有意思的小東西仍是很推薦的,官方例子不少,照着例子就能拼出一個不錯的遊戲。可是若是要重度使用,作一個功能複雜,大而全的遊戲,仍是不推薦了,由於他的文檔實在是太太太太爛了,我摸索了很久才弄明白它那自動生成的文檔應該怎麼看。還有就是一個隱藏bug,遇到了真是很難繞過去,好比cpu佔用太高、資源清理不掉、切換場景時候全局註冊插件失效、第三方插件的兼容等等。還有phaser生態不行,官方論壇發帖量少的可憐。另外phaser4立刻要出了,估計又是一次斷代更新。。。html
爲何要寫這個庫?
由於phaser寫一個小動效真的比較麻煩。
1.動效無非就是對元素進行縮放、位移、漸變。只要這三個變量組合得當就能夠得出舒服的效果,咱們要本身寫,沒有專業的ui、ue來幫咱們走查,很難控制好時間和幅度,而animte.css中的全部動畫,若是你讀了一下源碼,就知道必定是一個專業的動效師設計的。時間都精確到了小數點後兩位,位移曲線也不是用的css默認提供的那些。
2.phaser是純js的。用css寫一個左右晃動的動畫很簡單,只須要寫簡單幾行便可前端
@keyframes shake{ 0%{ transform: translateX(-10px); } 100%{ transform: translateX(10px); } } .shake{ animation: shake 1s ease; }
而phaser一個gameObject沒有基於自己的座標,咱們要基於世界座標來進行位移。而且也沒有提供不少默認的量供選擇,要進行手動轉換,好比translateX
就須要對x座標進行改變,translateY
須要對y座標進行改變,rotate
須要改變angle
值。java
實現步驟
1.對animate.css中全部css文件進行遍歷轉換爲js對象,我寫了一個postCSS插件來實現這個功能。
好比bounce動畫本來是這樣的git
@keyframes bounce { from, 20%, 53%, to { animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); transform: translate3d(0, 0, 0); } 40%, 43% { animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); transform: translate3d(0, -30px, 0) scaleY(1.1); } 70% { animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); transform: translate3d(0, -15px, 0) scaleY(1.05); } 80% { transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); transform: translate3d(0, 0, 0) scaleY(0.95); } 90% { transform: translate3d(0, -4px, 0) scaleY(1.02); } } .bounce { animation-name: bounce; transform-origin: center bottom; }
轉換完是這樣的github
module.exports = { "common": { "animation-name": "bounce", "transform-origin": "center bottom" }, "list": { "0": [ { "animation-timing-function": "cubic-bezier(0.215, 0.61, 0.355, 1)" }, { "transform": "translate3d(0, 0, 0)" } ], "20": [ { "animation-timing-function": "cubic-bezier(0.215, 0.61, 0.355, 1)" }, { "transform": "translate3d(0, 0, 0)" } ], "40": [ { "animation-timing-function": "cubic-bezier(0.755, 0.05, 0.855, 0.06)" }, { "transform": "translate3d(0, -30px, 0) scaleY(1.1)" } ], "43": [ { "animation-timing-function": "cubic-bezier(0.755, 0.05, 0.855, 0.06)" }, { "transform": "translate3d(0, -30px, 0) scaleY(1.1)" } ], "53": [ { "animation-timing-function": "cubic-bezier(0.215, 0.61, 0.355, 1)" }, { "transform": "translate3d(0, 0, 0)" } ], "70": [ { "animation-timing-function": "cubic-bezier(0.755, 0.05, 0.855, 0.06)" }, { "transform": "translate3d(0, -15px, 0) scaleY(1.05)" } ], "80": [ { "transition-timing-function": "cubic-bezier(0.215, 0.61, 0.355, 1)" }, { "transform": "translate3d(0, 0, 0) scaleY(0.95)" } ], "90": [ { "transform": "translate3d(0, -4px, 0) scaleY(1.02)" } ], "100": [ { "animation-timing-function": "cubic-bezier(0.215, 0.61, 0.355, 1)" }, { "transform": "translate3d(0, 0, 0)" } ] } }
插件代碼在這裏web
2.得到了包含css屬性的對象後,就須要寫一個轉換的映射關係,將每一個css屬性和對應的值解析爲phaser中tween動畫支持的參數,而後調用tween動畫來實現
映射關係代碼在這裏
此處有幾個小難點。一是不少動畫的timingFunc是二次貝塞爾曲線,須要使用bezier-easing
這個庫來計算,才能保證動畫速率保真。二是有些屬性想要轉換比較困難,我尚未想怎麼去作(主要是懶)。已知的有transform-origin
和skew
,由於phaser的實例中沒有關於這兩個屬性的概念。因此要本身手動實現。
3.關於結束狀態,是forwards
仍是backwards
要注意。npm
使用
DEMOcanvas