前端动画调研

8,348 阅读10分钟

动画调研

前言:动画从用途上可以分为两种,一种是展示型的动画,类似于一张GIF图,或者一段视频,另一种就是交互性的动画。这两种都有具体的应用场景,比如在我们信息流业务中,从下拉页面到进入活动页这个过程中,我们完全可以用一个展示型的入场动画代替原本可能只有一个小圆圈的的loading页。

展示型动画:

交互性动画(可以看到屏幕那个小手势):

一. 展示型动画 VS 交互性动画

展示型动画在实际使用的场景中,实现的方法很多,比如用gif图canvascss3动画等,但是最终输出的结果是不带有交互的,也就是从动画起始状态到结束状态一气呵成,这个过程用户可以感知,但是无法参与。对于交互性动画而言,我们可以在动画播放的某个时间节点触发相应的操作,进而让用户参与到其中,最常见的例子比如红包雨,或者是我们世界杯踢足球的动画,不仅仅能提升用户的体验,还能提升我们的产品的多元性。然而交互性动画经常面临的一个问题就是,通过原生代码实现交互动画是很复杂的,同时性能和兼容性是不得不认真考虑的问题,比较好的解决方案还是寻求相关的框架。

二. 动画使用到的技术

  • CSS3 Animation
  • canvas
  • SVG
  • WebGL
  • 利用JavaScript驱动的动画

伴随着CSS3的发展,利用CSS3的transform和动画的@keyframes就可以完成很多酷炫的动画,但是CSS3的动画应用场景仅仅是展示型动画,只要动画开始,我们就无法控制动画的状态,而且对于复杂的动画,CSS3就显得很无力了。对于JavaScript驱动的动画,在一定程度上就可以弥补这些缺点,比如anime.js增加的timeline的概念,通过将各部分动画链式执行,从而完成更为复杂的动画,同时动画执行的各个阶段提供的回调函数也能让我们更方便的控制动画执行的状态,为交互提供了可能。对于canvas,在 canvas上绘制的图形自身不支持 DOM 事件,只有canvas标签自身支持 DOM 事件监听。因此需要对 canvas 容器的事件进行处理,实现相对应事件的监听及处理。WebGL可以为canvas提供硬件GPU加速渲染,借助使用系统GPU可以在移动端中更流畅的展示动画.

三. 相关技术的兼容性

  • 对于CSS3的animation,兼容性如下:
  • canvas 兼容性如下:
  • WebGL 兼容性如下:

可以看到,CSS3的animation和canvas支持性比较好,只有WebGL在Android 4.4 Browser 完全不支持,后续我们会提到PixiJs库,可以采用WebGL渲染,也可以优雅降级采用canvas渲染

四. 现有的几种方案

1. AE + bodymovin + Lottie

适用场景:主要还是展示型动画

简介:通过 AE 上的 Bodymovin 插件将 AE 中制作好的动画导出成一个 json 文件,通过LottieJSON进行解析,最后以SVG/canvas/html的方式渲染动画。

官方文档:airbnb.io/lottie/ codepen仓库:codepen.io/collection/…

优点:

  • 跨平台,一次绘制、一次转换、随处可用
  • 文件更小,获取AE导出的JSON,最后通过lottie渲染为canvas/svg/html格式
  • 可以通过api操纵动画的一些属性,比如动画速度;添加动画各个状态的回调函数
  • 动画都是在After Effects中创建的,使用Bodymovin导出,并且本机渲染无需额外的工程工作。
  • 解放前端工程师的生产力,提高设计师做动效的自由度

缺点:

  • Bodymovin插件待完善,仍然有部分 AE 效果无法成功导出
  • 对于交互方面支持的还不是很好,更多的是用来展示动画
  • Lottiejson 文件的支持待完善,目前有部分能成功导出成 json文件的效果在移动端上无法很好的展现
  • 很多AE的效果是不支持的 查看支持的特性:Supported Features

2. Anime.js

适用场景: 强展示+弱交互性动画

简介:Anime.js是一个轻量级的js驱动的动画库,主要的功能有 - 支持keyframes,连接多个动画 - 支持Timeline,为实现更为复杂的动画提供了可能 - 支持动画状态的控制playback control,播放,暂停,重新启动,搜索动画或时间线。 - 支持动画状态的callback,在动画开始,执行中,结束时提供回调函数 - 支持svg动画 - 可以自定义贝塞尔曲线 - 任何包含数值的DOM属性都可以设置动画

GitHub:github.com/juliangarni… codepen仓库:codepen.io/collection/… 文档演示:animejs.com/documentati…

功能介绍:

  • 一定程度上,anime.js也是一个CSS3动画库,适用所有的CSS属性,并且实现的@keyframes能更方便的实现帧动画,替代CSS3复杂的定义方式。使用对象数组的形式定义每一帧 戳我:keyframes实例

    anime({
        targets: 'div',
        translateX: [
            { value: 250, duration: 1000, delay: 500, elasticity: 0 }, //第一帧
            { value: 0, duration: 1000, delay: 500, elasticity: 0 }    //第二帧
        ]
    })  //这个例子实现了目标元素在两帧中实现水平位移
    
  • 提供的Timeline能实现更为复杂的动画效果,通过这个Timeline,我们可以维护不同的动画之间的关系,进而通过多个不同的动画组成一个更为复杂的动画。 戳我:Timeline实例

    var myTimeline = anime.timeline();
    //通过.add()方法添加动画
    myTimeline
    .add({
        targets: '.square',
        translateX: 250
    })
    .add({
        targets: '.circle',
        translateX: 250
    })
    .add({
        targets: '.triangle',
        translateX: 250
    });
    
  • 动画播放的控制,常见的有暂停,重播,继续,动画状态的跟踪,自动播放,循环次数,抖动效果 戳我:playback controls实例

  • 为动画提供了回调函数,在动画或时间线完成的开始,期间或之时执行回调函数。 戳我:callback实例

    var myAnimation = anime({
        targets: '#begin .el',
        translateX: 250,
        delay: 1000,
    
        begin: function(anim) {   //        callback
            console.log(anim.began); //     true after 1000ms
        }
    });
    
  • 支持promise,动画结束后,调用anime.finished会返回一个promise对象戳我:promise实例

  • 支持svg绘制路径,目前不支持canvas绘制 戳我:SVG实例

  • 对于input这样带有数值的元素标签,也可以通过anime实例来设置动画 戳我:DOM ATTRIBUTES实例

    anime({
        targets: input,
        value: 1000, // Animate the input value to 1000
        round: 1 // Remove decimals by rounding the value
    });
    

优点:

  • 显而易见,anime.js不仅实现了CSS3动画的深度封装,更多的是通过js驱动来实现操作动画的状态,timeline实现了对于多个分支动画的管理,对于实现更为复杂的动画提供了可能
  • 通过anime.js提供的playback controlscallback,同时对于promise的支持,让我们对于动画的简单交互有了操作的空间
  • 虽然不支持canvas,但是支持svg绘制路径,我对svg还不是很了解,待之后深入学习后,在做一个补充。
  • 浏览器兼容性比较好,Android 4以上全部支持

缺点与不足:

  • anime.js做展示型动画是可以胜任的,在做交互性动画方面还是需要看场景,它更多适合做一些小型的交互动画,类似于通过触摸屏幕踢足球这种强交互的,anime.js就不是很有优势了。

3. PixiJs

适用场景:交互性动画,动画小游戏

简介:PixiJS是一个2D 渲染引擎, Pixi 主要负责渲染画面。可以创建丰富的交互式图形,动画和游戏,而无需深入了解WebGL API或处理浏览器和设备兼容性的问题。与此同时,PixiJS具有完整的WebGL支持,如果需要,可以无缝地回退到HTML5的canvas。PixiJs默认使用WebGL渲染,也可以通过声明指定canvas渲染,WebGL在移动端Android 4.4 browser并不支持,不过可以使用canvas优雅降级。

Github: github.com/pixijs/pixi… 官方文档: pixijs.download/release/doc… 官方网站:www.pixijs.com/ Examples:pixijs.io/examples/#/…

特性(摘自官方DOCS):

  • 支持WebGL渲染
  • 支持canvas 渲染(官方称PixiJS在canvas渲染方面现在是最快的)
  • 非常简单易用的API
  • 丰富的交互事件,比如完整的鼠标和移动端的触控事件
  • Pixi使用和 Canvas Drawing几乎一致的 api,但不同于Canvas的绘画 api,使用 Pixi 绘制的图形是通过WebGLGPU上渲染
  • 还有一系列特性需要在学习PixiJs之后了解

优势:

  • 最大优势莫过于通过WebGL来调用GPU渲染动画,这样极大的提升了性能
  • 无需深入了解WebGL API或者是浏览器兼容性(因为下面这条原因)
  • 支持canvas回退,当前设备不支持WebGL时,PixiJs会使用canvas渲染动画
  • 完整的DOCS,比较活跃的社区,有利于深入的学习。不过我感觉PixiJs学习成本相对来说还是很高的

缺点:

  • 首先是兼容的问题,WebGL在Android 4.4是不支持的,只能使用canvas进行降级
  • Pixi 主要负责渲染画面,很多其它功能开发者得自己写或搭配其它库来使用,不过按照目前来看,是满足我们的需求的。

性能:

  • 对于手机版本Android4.4 以上的手机,除了代码层面造成的性能不足,通过WebGL调用GPU渲染,性能还是有保障的。然而对于Android4.4只能使用canvas渲染,性能还是要看动画的复杂度,以及代码的优化

五. 总结

针对不同的动画需求,我总结了三种不同场景下的动画库。对于展示性的动画,我们完全可以使用第一种方案,让设计同学提供动画,我们利用动画导出的JSON,将动画还原为svg/canvas/html。如果场景是交互型或者需要做一个小游戏,可以采用第三种方案PixiJs,通过WebGL来渲染,利用硬件资源,极大的提升性能,在兼容性方面,对于不支持WebGL的浏览器,可以使用canvas渲染平稳回退。最后一种场景就是弱交互强展示,这种场景往往就是用户点击一下暂停执行相应操作,待操作完成继续播放动画,交互方面比较偏弱,这种场景下可以采用第二种方案 Anime.js,Anime.js不仅仅支持所有的css 属性,而且可以通过Timeline,callback, playback controls来控制动画执行的各个状态。而且兼容性满足我们的需求,在性能方面,只要不过多的造成页面回流,多使用transform操作复合层,性能还是可以的(待多多尝试,就我看的几个例子性能还是不错的)。最后,从需求角度分析之后,从学习成本做个简单的小排名:PixiJs > Anime.js > lottie

六.动画性能分析参考

七. 参考链接