首先介绍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