实现phaser版的animate.css动效库

阿古达木

首先介绍phaser和animate.css

animate.css相信大部分做前端的同学都用过,是一款强大的css动画库,里面有上百种常用小动效。简单的加一个类名就可以让我们写的页面变得生动有趣起来。是由css的keyframes来实现的。

phaser是一款js游戏引擎,基于canvas和webgl。内置各种功能,比如精灵,spine,音视频,dragonBones,物理引擎,粒子效果等等。不向cocos,白鹭等是一个大生态全家桶,phaser很灵活,很容易插入到现有项目中。我之前深入使用过一段时间,怎么硕呢,如果你是个人玩票性质想写点有意思的小东西还是很推荐的,官方例子很多,照着例子就能拼出一个不错的游戏。但是如果要重度使用,做一个功能复杂,大而全的游戏,还是不推荐了,因为他的文档实在是太太太太烂了,我摸索了好久才弄明白它那自动生成的文档应该怎么看。还有就是一个隐藏bug,遇到了真是很难绕过去,比如cpu占用过高、资源清理不掉、切换场景时候全局注册插件失效、第三方插件的兼容等等。还有phaser生态不行,官方论坛发帖量少的可怜。另外phaser4马上要出了,估计又是一次断代更新。。。

为什么要写这个库?
因为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值。

实现步骤
1.对animate.css中所有css文件进行遍历转换为js对象,我写了一个postCSS插件来实现这个功能。
比如bounce动画原本是这样的

@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;
}

转换完是这样的

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)"
            }
        ]
    }
}

插件代码在这里

2.获得了包含css属性的对象后,就需要写一个转换的映射关系,将每个css属性和对应的值解析为phaser中tween动画支持的参数,然后调用tween动画来实现
映射关系代码在这里
此处有几个小难点。一是很多动画的timingFunc是二次贝塞尔曲线,需要使用bezier-easing这个库来计算,才能保证动画速率保真。二是有些属性想要转换比较困难,我还没有想怎么去做(主要是懒)。已知的有transform-originskew,因为phaser的实例中没有关于这两个属性的概念。所以要自己手动实现。
3.关于结束状态,是forwards还是backwards要注意。

使用
DEMO

NPM

阅读 1k

牛逼的工程师就是能用简单的代码和思路写出复杂的功能

465 声望
15 粉丝
0 条评论

牛逼的工程师就是能用简单的代码和思路写出复杂的功能

465 声望
15 粉丝
文章目录
宣传栏