作者:vivo 互联网前端团队- ZhaoJie

本文将从各个角度来对动画整个体系进行分类,并且介绍各种前端动画的实现办法,最初咱们将总结在理论开发中的各个场景的动画抉择计划。

一、背景

前端动画场景需要多

对泛滥动画场景的技术实现计划抉择上比拟含糊

各动画计划的优劣及实用场景意识含糊

现有动画库太多,不晓得选哪个

支流动画库的实用场景意识含糊

上面首先让咱们从各个角度来对动画整个体系进行分类,让咱们清晰的理解动画整个体系。

二、分类

2.1 用处角度

首先咱们从动画的用处或者说是业务的角度来进行辨别,将咱们平时的动画分为展现型动画和交互型动画。

2.1.1 展现型动画

相似于一张GIF图,或者一段视频。比方在开启宝箱的时候,咱们会退出一个切场过渡动画,来代替原有的僵硬期待后果。

展现型动画在理论应用的场景中,实现的办法很多,比方用GIF图,canvas,CSS3动画等,然而最终输入的后果是不带有交互的,也就是从动画起始状态到完结状态零打碎敲,这个过程用户能够感知,然而无奈参加

2.1.2 交互型动画

用户自已参加的,对于交互性动画而言,咱们能够在动画播放的某个工夫节点触发相应的操作,进而让用户参加到其中,最常见的例子红包雨,不仅仅能晋升用户的体验,还能晋升咱们的产品的多元性。

然而交互性动画常常面临的一个问题就是,通过原生代码实现交互动画是很简单的,同时性能和兼容性是不得不认真思考的问题,比拟好的解决方案还是寻求相干的框架。

2.2 绘制技术角度

不论采纳什么形式来制作动画,最终出现到前端页面的无非是以下三种模式:

  1. Canvas
  2. div
  3. SVG
PS:为了简略也能够用视频,但除非动画的播放场景固定,不然挪动端视频在不同app、不同机型、不同零碎的播放显示都不太一样,容易踩不少坑。

2.2.1 不同绘制技术的性能差别

Canvas

  • 效率高、性能好、可控性高,只能解决位图,内存占用恒定
  • 依赖分辨率
  • 不反对事件处理器
  • 弱的文本渲染能力
  • 可能以 .png 或 .jpg 格局保留后果图像
  • 最适宜图像密集型的游戏,其中的许多对象会被频繁重绘

div

  • 包含CSS管制的DOM动画、JS管制的DOM动画
  • 比拟适宜简略的数量较少的复杂度较低的动画

SVG

  • 解决矢量图,不失真
  • 不依赖分辨率
  • 反对事件处理器
  • 最适宜带有大型渲染区域的应用程序(比方谷歌地图)
  • 复杂度高会减慢渲染速度(任何适度应用 DOM 的利用都不快)
  • 不适宜游戏利用

2.2.2 Canvas和SVG比拟

一句话总结:都是2D做图,svg是矢量图,canvas是位图。canvas 是逐像素进行渲染的,适宜游戏。

SVG

  • SVG绘制的是矢量图,缩放不影响显示,所以最适宜带有大型渲染区域的应用程序(比方谷歌地图)
  • SVG 是一种应用 XML 形容 2D 图形的语言。
  • SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您能够为某个元素附加 JavaScript 事件处理器。
  • 在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器可能主动重现图形。

Canvas

  • Canvas 通过 JavaScript 来绘制 2D 图形。
  • Canvas 是逐像素进行渲染的。
  • 在 Canvas 中,一旦图形被绘制实现,它就不会持续失去浏览器的关注。如果其地位发生变化,那么整个场景也须要从新绘制,包含任何或者已被图形笼罩的对象。
  • Canvas只占用一个DOM节点,在做一些烟花、飘雪等静止元素很多的动画时,会比CSS/SVG性能好。

性能比拟

  • 个别状况下,随着屏幕大小的增大,canvas将开始降级,因为须要绘制更多的像素。
  • 随着屏幕上的对象数目增多,SVG 将开始降级,因为咱们正一直将这些对象增加到 DOM 中。
  • 这些度量不肯定精确,以下方面的不同肯定会引起变动:实现和平台、是否应用齐全硬件加速的图形,以及 JavaScript 引擎的速度。

2.3 动画类型角度

前端动效开发,首先应该确定的是

动画用处->确认动画类型->确认绘制技术->确认动画的实现形式。

尽管最终出现动画的载体(绘制技术)就三种,但实现动画的形式却很多,得从动画类型登程探讨动画的实现形式:

(1)逐帧动画(序列帧动画)

  • GIF实现
  • CSS实现(animation)
  • JS+DOM实现
  • JS+canvas实现

(2)补间动画(Tween动画\关键帧动画)

  • CSS实现(transition、animation等)应用一些缓动函数
  • JS实现

(3)SVG动画

  • 应用 XML 格局定义图形
  • 能够用AI等SVG编辑工具生成SVG图片后,配合anime.js、GSAP等现有库进行动画制作

(4)骨骼动画

  • 个别采纳Spine、DragonBones等工具导出相应资源图片和JSON动画配置资源后应用。

(5)3D动画

  • DOM操作用CSS 3D实现。(perspective属性、css3d-engine)
  • 场景搭建用webGL(Three.js等)
  • 3D模型动画用Blender或maya等制作实现后导出应用

2.3.1 逐帧动画(序列帧动画)

逐帧动画是在工夫帧上逐帧绘制帧内容,因为是一帧一帧的画,所以逐帧动画具备十分大的灵活性,简直能够体现任何想体现的内容。

因为逐帧动画的帧序列内容不一样,不仅减少制作累赘而且最终输入的文件量也很大,但它的劣势也很显著:因为它类似与电影播放模式,很适宜于表演很细腻的动画,如3D成果、人物或动物急剧转身等等成果。

所以逐帧动画的实现外围是什么,就是将咱们的这些动态的图片进行疾速的循环播放,造成了一个动静的动画成果。这就是帧动画。
2.3.1.1 GIF实现

咱们能够将帧动画导出成GIF图,GIF图会间断播放,无奈暂停,它往往用来实现小细节动画,老本较低、使用方便。但其毛病也是很显著的:

  1. 画质上,GIF 反对色彩少(最大256色)、Alpha 透明度反对差,图像锯齿毛边比较严重;
  2. 交互上,不能间接管制播放、暂停、播放次数,灵活性差;
  3. 性能上,GIF 会引起页面周期性的绘画,性能较差。
2.3.1.2 CSS实现

CSS3帧动画是咱们明天须要重点介绍的计划,最外围的是利用CSS3中Animation动画,确切的说是应用animation-timing-function 的阶梯函数 steps(number\_of\_steps, direction) 来实现逐帧动画的间断播放。

帧动画的实现原理是一直切换视觉内图片内容,利用视觉滞留生理景象来实现间断播放的动画成果,上面咱们来介绍制作CSS3帧动画的几种计划。

(1)间断切换动画图片地址src(不举荐)

咱们将图片放到元素的背景中(background-image),通过更改 background-image 的值实现帧的切换。然而这种形式会有以下几个毛病,所以该计划不举荐。

  • 多张图片会带来多个 HTTP 申请
  • 每张图片首次加载会造成图片切换时的闪动
  • 不利于文件的治理

(2)间断切换雪碧图地位(举荐)咱们将所有的帧动画图片合并成一张雪碧图,通过扭转 background-position 的值来实现动画帧切换。分两步进行:

步骤一:

将动画帧合并为雪碧图,雪碧图的要求能够看下面素材筹备,比方上面这张帧动画雪碧图,共20帧。

步骤二:

应用steps阶梯函数切换雪碧图地位

写法一:

<div class="sprite"></div>.sprite {    width: 300px;    height: 300px;    background-repeat: no-repeat;    background-image: url(frame.png);    animation: frame 333ms steps(1,end) both infinite;}@keyframes frame {    0% {background-position: 0 0;}    5% {background-position: -300px 0;}    10% {background-position: -600px 0;}    15% {background-position: -900px 0;}    20% {background-position: -1200px 0;}    25% {background-position: -1500px 0;}    30% {background-position: -1800px 0;}    35% {background-position: -2100px 0;}    40% {background-position: -2400px 0;}    45% {background-position: -2700px 0;}    50% {background-position: -3000px 0;}    55% {background-position: -3300px 0;}    60% {background-position: -3600px 0;}    65% {background-position: -3900px 0;}    70% {background-position: -4200px 0;}    75% {background-position: -4500px 0;}    80% {background-position: -4800px 0;}    85% {background-position: -5100px 0;}    90% {background-position: -5400px 0;}    95% {background-position: -5700px 0;}    100% {background-position: -6000px 0;}}

针对以上动画有疑难?

问题一:既然都具体定义关键帧了,是不是能够不必steps函数了,间接定义linear变动不就好了吗?

animation: frame 10s linear both infinite;

如果咱们定义成这样,动画是不会阶梯状,一步一步执行的,而是会间断的变动背景图地位,是挪动的成果,而不是切换的成果,如下图:

问题二: 不是应该设置为20步吗,怎么变成了1?

这里咱们先来理解下animation-timing-function属性。CSS animation-timing-function属性定义CSS动画在每一动画周期中执行的节奏。

综上咱们能够晓得,因为咱们具体定义了一个动画周期,也就是说0% ~ 5%之间变动一次,5% ~ 10%变动一次,所以咱们这样写能力达到想要的成果。

写法二:

<div class="sprite"></div>.sprite {    width: 300px;    height: 300px;    background-repeat: no-repeat;    background-image: url(frame.png);    animation: frame 333ms steps(20) both infinite;}@keyframes frame {    0% {background-position: 0 0;}//可省略    100% {background-position: -6000px 0;}}

这里咱们定义了关键帧的开始和完结,也就是定义了一个关键帧周期,但因为咱们没有具体的定义每一帧的展现,所以咱们要将0%~100%这个区间分成20步来阶段性展现。

(3)间断挪动雪碧图地位(挪动端举荐)

跟第二种基本一致,只是切换雪碧图的地位过程换成了transform:translate3d()来实现,不过要加多一层overflow: hidden;的容器包裹,这里咱们以只定义初始和完结帧为例,应用transform能够开启GPU减速,进步机器渲染成果,还能无效解决挪动端帧动画抖动的问题。

<div class="sprite-wp">    <div class="sprite"></div></div>.sprite-wp {    width: 300px;    height: 300px;    overflow: hidden;}.sprite {    width: 6000px;    height: 300px;    will-change: transform;    background: url(frame.png) no-repeat center;    animation: frame 333ms steps(20) both infinite;}@keyframes frame {  0% {transform: translate3d(0,0,0);}    100% {transform: translate3d(-6000px,0,0);}}

steps() 函数详解

从下面的代码咱们能够发现,CSS实现的外围就是应用animation-timing-function缓动函数的阶梯函数steps(number\_of\_steps, direction)来实现逐帧动画的间断播放的。

接着咱们来理解下steps() 函数:

steps 指定了一个阶梯函数,蕴含两个参数:

  • 第一个参数指定了函数中的距离数量(必须是正整数);
  • 第二个参数可选,指定在每个距离的终点或是起点产生阶跃变动,承受 start 和 end 两个值,默认为 end。
  • start 第一帧是第一步动画的完结,end 第一帧是第一步动画的开始。

除了 steps 函数,animation-timing-function 还有两个与逐帧动画相干的属性值 step-start 与 step-end:

  • step-start 等同于 steps(1,start)
  • step-end 等同于 steps(1,end)
2.3.1.3 JS实现

(1)通过JS来管制img的src属性切换(不举荐)

和下面CSS3帧动画外面切换元素background-image属性一样,会存在多个申请等问题,所以该计划咱们不举荐,然而这是一种解决思路。

(2)通过JS来管制canvas图像绘制

通过canvas制作帧动画的原理是用drawImage办法将图片绘制到canvas上,一直擦除和重绘就能失去咱们想要的成果。

<canvas id="canvas" width="300" height="300"></canvas>(function () {    var timer = null,        canvas = document.getElementById("canvas"),        context = canvas.getContext('2d'),        img = new Image(),        width = 300,        height = 300,        k = 20,        i = 0;    img.src = "frame.png";    function drawImg() {        context.clearRect(0, 0, width, height);        i++;        if (i == k) {            i = 0;        }        context.drawImage(img, i * width, 0, width, height, 0, 0, width, height);        window.requestAnimationFrame(drawImg);    }    img.onload = function () {        window.requestAnimationFrame(drawImg);    }})();

下面是通过扭转裁剪图像的X坐标地位来实现动画成果的,也能够通过扭转画布上搁置图像的坐标地位实现,如下:

context.drawImage(img, 0, 0, width*k, height,-i*width,0,width*k,height);

(3)通过JS来管制CSS属性值变动

这种形式和后面CSS3帧动画一样,有三种形式,一种是通过JS切换元素背景图片地址background-image,一种是通过JS切换元素背景图片定位background-position,最初一种是通过JS挪动元素transform:translate3d(),第一种不做介绍,因为同样会存在多个申请等问题,不举荐应用,这里实现前面两种。

切换元素背景图片地位 background-position
.sprite {    width: 300px;    height: 300px;    background: url(frame.png) no-repeat 0 0;}<div class="sprite" id="sprite"></div>(function(){    var sprite = document.getElementById("sprite"),      picWidth = 300,      k = 20,      i = 0,      timer = null;    // 重置背景图片地位    sprite.style = "background-position: 0 0";    // 扭转背景图地位    function changePosition(){        sprite.style = "background-position: "+(-picWidth*i)+"px 0";        i++;        if(i == k){            i = 0;        }        window.requestAnimationFrame(changePosition);    }    window.requestAnimationFrame(changePosition);})();
挪动元素背景图片地位 transform:translate3d()
.sprite-wp {   width: 300px;    height: 300px;    overflow: hidden;}.sprite {    width: 6000px;    height: 300px;    will-change: transform;    background: url(frame.png) no-repeat center;}<div class="sprite-wp">    <div class="sprite" id="sprite"></div></div>(function () {    var sprite = document.getElementById("sprite"),        picWidth = 300,        k = 20,        i = 0,        timer = null;    // 重置背景图片地位    sprite.style = "transform: translate3d(0,0,0)";    // 扭转背景图挪动    function changePosition() {        sprite.style = "transform: translate3d(" + (-picWidth * i) + "px,0,0)";        i++;        if (i == k) {            i = 0;        }        window.requestAnimationFrame(changePosition);    }    window.requestAnimationFrame(changePosition);})();
2.3.1.4 性能剖析

咱们通过Chrome浏览器的各种工具,查看了每种计划的 FPS、CPU占用率、GPU占用、Scripting、Rendering、Painting、内存的应用状况,失去以下数据:

通过剖析以上数据咱们能够得出以下几点:

  1. 除了CSS transform:translate3d() 计划,其余计划的FPS都能达到60FPS的晦涩水平,但该计划的FPS 也不是很低。
  2. CPU占用率最低的计划是
    CSS transform:translate3d() 计划。
  3. GPU占用最低的计划是JS canvas 绘制计划。
  4. CSS 计划没有脚本开销。
  5. Rendering 起码的是
    CSS transform:translate3d() 计划。
  6. Painting 起码的是
    CSS transform:translate3d() 计划。
  7. 各计划内存占用区别不大。

论断:咱们看到,在7个指标中,CSS transform:translate3d() 计划将其中的4个指标做到了最低,从这点看,咱们齐全有理由抉择这种计划来实现CSS帧动画。

2.3.2 补间动画(Tween动画\关键帧动画)

补间动画是动画的根底模式之一,又叫做两头帧动画,突变动画,指的是人为设定动画的要害状态,也就是关键帧,而关键帧之间的过渡过程只须要由计算机解决渲染的一种动画模式。

说白了,就是咱们在做动画的时候,只须要指定几个非凡时刻动画的状态,其余的状态由计算机主动计算补充。

实现补间动画常见的伎俩次要由以下几种:

  • CSS3 Animation:通过animation(除steps()以外的工夫函数)属性在每个关键帧之间插入补间动画。
  • CSS3 Transition:区别于animation,transition只能设定初始和完结时刻的两个关键帧状态。
  • 利用JavaScript实现动画:例如JavaScript动画库或框架,Anime.js 或者TweenJS,它是CreateJS的其中一个套件。另外,在Flash业界久负盛名的GreenSock推出的GSAP(GreenSock Animation Platform)也新引入了对Javascript动画的反对。
2.3.2.1 CSS实现

(1)transition 动画

transition容许CSS的属性值在肯定的工夫区间内平滑地过渡,即指定元素的初始状态 和开端状态,既能够实现一个动画,两头的变动齐全有浏览器本人决定。动画的成果次要还是看transition相干属性即可。

然而利用transition制作的动画也有着显著的毛病:

  1. transition须要事件触发,所以没法在网页加载时主动产生。
  2. transition是一次性的,不能反复产生,除非一再触发。
  3. transition只能定义开始状态和完结状态,不能定义中间状态,也就是说只有两个状态。
  4. 一条transition规定,只能定义一个属性的变动,不能波及多个属性。

(2)animation 动画

利用animation能够实现一个残缺的CSS补间动画,如下面所说,咱们只须要定义几个非凡时刻的动画状态即可。这个非凡时刻通常咱们叫做关键帧。

keyframes 关键帧

Keyframes具备其本人的语法规定,他的命名是由"@keyframes"结尾,前面紧接着是这个“动画的名称”加上一对花括号“{}”,括号中就是一些不同时间段款式规定,有点像咱们CSS的款式写法一样。

对于一个"@keyframes"中的款式规定是由多个百分比形成的,如“0%”到"100%"之间,咱们能够在这个规定中创立多个百分比,咱们别离给每一个百分比中给须要有动画成果的元素加上不同的属性,从而让元素达到一种在一直变动的成果,比如说挪动,扭转元素色彩,地位,大小,形态等。

不过有一点须要留神的是,咱们能够应用“fromt”“to”来代表一个动画是从哪开始,到哪完结,也就是说这个 "from"就相当于"0%"而"to"相当于"100%",值得一说的是,其中"0%"不能像别的属性取值一样把百分比符号省略,咱们在这里必须加上百分符号(“%”)如果没有加上的话,咱们这个keyframes是有效的,不起任何作用。因为keyframes的单位只承受百分比值。看一下具体的代码:

@keyframes IDENT {    from {        Properties:Properties value;    }    Percentage {        Properties:Properties value;    }    to {        Properties:Properties value;    }}/*或者全副写成百分比的模式:*/@keyframes IDENT {    0% {        Properties:Properties value;    }    Percentage {        Properties:Properties value;    }    100% {        Properties:Properties value;    }}

其中IDENT是一个动画名称,你能够轻易取,当然语义化一点更好,Percentage是百分比值,咱们能够增加许多个这样的百分比,Properties为CSS的属性名,比如说left,background等,value就是绝对应的属性的属性值。

2.3.2.2 JS实现

利用JavaScript实现动画,能够采纳开源的JavaScript动画库或框架进行实现,例如:Anime.js或者TweenJS 上面咱们以Anime.js为例进行演示如何实现一个补间动画。

肯定水平上,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 });

2.3.3 SVG动画

当咱们在实现动画的时候,缓缓会发现,大部分的元素都是图片,而且图片是提前预设好的,不能更改,只能用新的图片替换,例如当咱们要实现微笑动画的时候,须要画两张图,一幅是闭着嘴的,一幅是张嘴笑的,而后逐帧播放。这样的画面当你有足够多帧图片的时候,并不会看出僵硬,一旦低于 24 帧就是变得不天然了,那怎么在不减少工作量的前提下,实现晦涩的变动呢?咱们将关键帧动画的思维嫁接到元素本身扭曲变动上,就催生出了「柔性动画」的概念。

2.3.3.1 SVG动画解说

从上图能够看出,元素之间是能够互相变动的,而且十分的晦涩,这样的动画并不需要 canvas 这种重武器,简略的 DOM 就能够实现,SVG 真的是一个神器,不仅在实现图标,字体上特点显明,在实现柔性动画方面也自成一家。

SVG 仍然是 DOM ,他有本人独有的 Animation 标签,但也反对 CSS 的属性,其实现动画的实质是依赖于线条和填充,线条的变动,导致填充区域的扭转,从而引起形态的变动。而线条则依赖于门路和锚点,门路和锚点的扭转,间接影响了线条的变动。

能够用AI等SVG编辑工具生成SVG图片后,配合anime.js、GSAP等现有库进行动画制作。

上面咱们通过anime.js来实现一个SVG门路动画.

SVG 绘制门路

戳我:SVG实例

var path = anime.path('.motion-path-demo path');anime({  targets: '.motion-path-demo .el',  translateX: path('x'),  translateY: path('y'),  rotate: path('angle'),  easing: 'linear',  duration: 2000,  loop: true});

2.3.4 骨骼动画

SVG 实现的动画比拟部分和玲珑,应用范畴也比拟狭隘,然而当咱们实现简单的柔性动画,甚至游戏的时候,就还是须要用骨骼动画来实现。

从上图咱们能够看到龙的翅膀是一张图片,然而能够通过图片的部分的扭曲和变形,来实现鼓动翅膀时带来的肌肉膨胀和舒张。这样的动画是怎么实现的呢?这就要引出骨骼动画中,一个十分重要的概念:网格

这里咱们比拟通俗的探讨下这个概念,要实现图片的部分变动,咱们就要把图片分块,分的每一块就称为网格,每个网格都有本人的顶点和边,顶点的位移会引起网格形态的变动,形态的变动就会带来所从属的图片的变动。网格的概念是不是很像门路和锚点,不论怎样的技术,在实现逻辑上都大同小异,重要的不是始终盯着不同和变动的局部,而是发现那些不变的中央,能力达到举一反三的成果。

制作这样的动画并不简单,你能够应用相似 Spine 和 DragonBones 这样的工具,然而做动画真的是一个体力活,你须要一直的调试,以求达到一种让人看起来难受的状态。

2.3.4.1 骨骼动画解说

骨骼动画就是把角色的各局部身材部件图片绑定到一根根相互作用连贯的“骨头”上,通过管制这些骨骼的地位、旋转方向和放大放大而生成的动画。

咱们常说的骨骼动画个别分为两个局部:

  1. 骨架(Skeleton)
  2. 蒙皮(Skin)

骨架波及的数据包含两个:

  • 一是骨架的拓扑构造(连贯、父子关系)。
  • 二是骨架的各种pose,也就是每个动作对应的整个骨架的地位信息。

蒙皮则表白的是附丽在骨骼上的顶点的信息。

骨骼绑定的过程就是确定每个顶点受哪几根骨骼的影响,每根骨骼影响的权重有多大,譬如肘部的皮肤可能同时受大臂和小臂两根骨头的影响,而远离手肘的局部可能就只受小臂骨头影响。个别在3D骨骼动画里,每个顶点最多反对4-8根骨骼同时影响它就曾经能够很准确地表白整个蒙皮的成果了。

  • 骨骼动画的劣势:

骨骼动画比传统的逐帧动画要求更高的处理器性能,但同时它也具备更多的劣势:

  1. 动画更加活泼真切。
  2. 图片资源占最小的存储空阔:骨骼动画的图片容量能够缩小90%(配置文件H5的压缩计划前面详解)。
  3. 动画切换主动补间:过渡动画主动生成,让动作更加灵动。
  4. 骨骼可控 :能够通过代码管制骨骼,轻松实现角色配备更换,甚至可对某骨骼做非凡管制或事件监听。
  5. 骨骼事件帧:动画执行到某个动作或某个帧,触发自定义事件行为。
  6. 动作数据继承:多角色可共用一套动画数据。
  7. 可联合物理引擎和碰撞检测。
2.3.4.2 骨骼动画制作

首先咱们来理解一下,骨骼动画是如何进行制作的:

制作骨骼动画次要是应用 Spine 和 DragonBones 这样的工具进行制作。
  • DragonBones

DragonBones是从Flash动画开始创作的,初衷是减小资源量,同时实现更为细粒度的动作(比方交互式的),让美术从繁琐的逐帧绘制Sprie Sheet的工作中解放出来,所以它把一个角色每一帧的sprite sheet拆分成一个个更小的根本图块,譬如胳膊,腿,躯干等等,而每个根本图块依然是最小的可管制单位。

以下游戏&渲染引擎都反对渲染DragonBones导出的文件:

  • Spine

Spine 是一款针对游戏开发的 2D 骨骼动画编辑工具。Spine 旨在提供更高效和简洁 的工作流程,以创立游戏所需的动画。

业界免费业余2D骨骼动画编辑工具,动画设计师举荐易用稳固,以下游戏&渲染引擎都反对渲染Spine导出的文件:

上面咱们来制作一个骨骼动画小案例

  • 创立骨骼

首先咱们须要创立手部的骨骼,如下图所示:

  1. 1确保左上角为SETUP模式
  2. 确保选中左边视图中的根骨骼,创立骨骼时必须要选中父骨骼
  3. 单击左下角的Create按钮
  4. 开始顺次创立出5根骨骼
  5. 创立蒙皮网格

而后咱们须要给手部创立蒙皮网格(MESH),如下图所示:

首先,单击创立骨骼的Create按钮,退出骨骼创立模式

  1. 选中手部贴图(Attachment)
  2. 勾选其底部的Mesh选项
  3. 单击右下角的Edit按钮
  4. 呼出了Edit Mesh菜单
  5. 勾选Edit Mesh菜单中的Deformed选项
  6. 单击Edit Mesh菜单中的Create按钮
  7. 开始在手部创立网格顶点
  8. 能够单击Edit Mesh菜单中的Modify按钮对顶点进行位移
  9. 设置网格点权重

咱们须要给网格顶点设置各个骨骼的权重,整个过程如下图所示:

首先,敞开Edit Mesh菜单

  1. 确认勾选的还是手部的贴图
  2. 单击左下角的Weights按钮,呼出Weights菜单
  3. 单击Weights菜单底部的Bind按钮,来绑定骨骼
  4. 抉择手部的五根骨骼,直到它们都呈现Weights菜单里,留神不同的骨骼色彩是不一样的
  5. 单击Weights菜单的Auto按钮或者按esc键,来触发Spine的主动权重计算
  6. 勾选Weights菜单的Overlay,咱们能够看到绑定后的权重热力求
  7. 动起来!

当初咱们要让手动起来了,咱们只展现一个蜿蜒手臂的动画即可。

首先,咱们须要设置关键帧,让咱们在第1帧和第30帧设置好关键帧,这两个关键帧对应的手臂地位是齐全一样的,因为咱们须要循环播放动画。

具体步骤如下图:

  1. 确保左上角的模式处于ANIMATE模式
  2. 选中手部的五根骨骼(按住cmd键或control键顺次点选)
  3. 选中第0帧
  4. 单击Rotate下的钥匙按钮,咱们对手臂的旋转属性设置关键帧
  5. 抉择第30帧
  6. 反复第4步的操作,使第30帧的关键帧与第0帧完全相同

接下来咱们只需微微旋转手臂,并在0-30帧两头找一个帧当做关键帧即可:咱们抉择第15帧作为两头的关键帧。

  1. 抉择第15帧
  2. 确保Rotate按钮被选中
  3. 向上旋转5根骨骼到一个角度
  4. 按下K帧按钮进行关键帧设置
  5. 按下播放按钮来预览动画

额定的,我给另一只手、嘴巴、脸部和头发都做了MESH,以下是动画的效果图:

2.3.4.3 前端展现骨骼动画

用Spine将制作好的骨骼动画进行导出输入资源(合图信息文件:atlas;动画信息文件:json,图片合图:png),将这些资源交由前端进行展现。

前端开发依据Spine或者DragonBones可能反对的渲染引擎,在我的项目中导入渲染引擎进行展现骨骼动画。

2.3.5 3D动画

前端3D动画实现能够通过perspective属性操作用CSS 3D来实现,或者间接借助开源的Three.js开源库进行实现。

因为3D动画波及的内容较多,篇幅无限,前面咱们将专门开一章来解说前端3D动画。

三、现有计划总结

3.1 纯CSS实现

适宜场景: 简略的展现型动画

应用transition\animation属性,设置相应的关键帧状态,并且借助一些缓动函数来进行实现一些简单化的动画。

长处:开发成本低,不须要导入任何额定的依赖包

毛病与有余:只可能胜任做一些比拟简单化的动画,无奈实现一些过于负责的动画。

3.2 Anime.js

实用场景: 简略的展现型动画+弱交互型动画

Anime.js是一个轻量级的js驱动的动画库,次要的性能有:

  1. 反对keyframes,连贯多个动画
  2. 反对Timeline,为实现更为简单的动画提供了可能
  3. 反对动画状态的管制playback control,播放,暂停,重新启动,搜寻动画或工夫线。
  4. 反对动画状态的callback,在动画开始,执行中,完结时提供回调函数
  5. 反对SVG动画
  6. 能够自定义贝塞尔曲线
  7. 任何蕴含数值的DOM属性都能够设置动画
  8. GitHub:
    https://github.com/juliangarn...
  9. codepen仓库:
    https://codepen.io/collection...
  10. 文档演示:
    http://animejs.com/documentat...

性能介绍:

肯定水平上,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 controls和callback,同时对于promise的反对,让咱们对于动画的简略交互有了操作的空间。
  • 尽管不反对canvas,然而反对svg绘制门路。
  • 浏览器兼容性比拟好,Android 4以上全副反对。

毛病:

Anime.js做展现型动画是能够胜任的,然而对于特地简单的动画也是不太可能实现,在做交互性动画方面还是须要看场景,它更多适宜做一些小型的交互动画,相似于通过触摸屏幕踢足球这种强交互的,anime.js就不是很有劣势了。

3.3 Lottie

实用场景: 简单的展现型动画

通过 AE 上的 Bodymovin 插件将 AE 中制作好的动画导出成一个 json 文件,通过Lottie对JSON进行解析,最初以SVG/canvas/html的形式渲染动画。

可能完整的展现设计师设计的各种各样简单的动画。

  • 官网文档:
    http://airbnb.io/lottie/
  • codepen仓库:
    https://codepen.io/collection...

长处:

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

毛病:

  • Bodymovin 插件待欠缺,依然有局部 AE 成果无奈胜利导出。
  • 对于交互方面反对的还不是很好,更多的是用来展现动画。
  • Lottie 对 json 文件的反对待欠缺,目前有局部能胜利导出成 json 文件的成果在挪动端上无奈很好的展示。
  • 很多AE的成果是不反对的 查看反对的个性:Supported Features。

3.4 PixiJs

实用场景: 交互型动画,动画小游戏

PixiJS是一个2D 渲染引擎, Pixi 次要负责渲染画面。能够创立丰盛的交互式图形,动画和游戏,而无需深刻理解WebGL API或解决浏览器和设施兼容性的问题。与此同时,PixiJS具备残缺的WebGL反对,如果须要,能够无缝地回退到HTML5的canvas。PixiJs默认应用WebGL渲染,也能够通过申明指定canvas渲染,WebGL在挪动端Android 4.4 browser并不反对,不过能够应用canvas优雅降级。

  • Github: https://github.com/pixijs/pix...
  • 官网文档:http://pixijs.download/releas...
  • 官方网站:http://www.pixijs.com/
  • Examples:https://pixijs.io/examples/#/...

个性(摘自官网DOCS):

  • 反对WebGL渲染
  • 反对canvas 渲染(官网称PixiJS在canvas渲染方面当初是最快的)
  • 非常简单易用的API
  • 丰盛的交互事件,比方残缺的鼠标和挪动端的触控事件
  • Pixi应用和 canvas Drawing简直统一的 api,但不同于 canvas 的绘画 api,应用 Pixi 绘制的图形是通过 WebGL 在 GPU 上渲染
  • 还有一系列个性须要在学习PixiJs之后理解

长处:

  • 最大劣势莫过于通过WebGL来调用GPU渲染动画,这样极大的晋升了性能。
  • 无需深刻理解WebGL API或者是浏览器兼容性(因为上面这条起因)。
  • 反对canvas回退,以后设施不反对WebGL时,PixiJs会应用canvas渲染动画。
  • 残缺的DOCS,比拟沉闷的社区,有利于深刻的学习。不过我感觉PixiJs学习老本相对来说还是很高的。

毛病:

  • 首先是兼容的问题,WebGL在Android 4.4 是不反对的,只能应用canvas进行降级。
  • Pixi 次要负责渲染画面,很多其它性能开发者得本人写或搭配其它库来应用,不过依照目前来看,是满足咱们的需要的。

性能:

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

3.5 总结

简略的展现型动画:

对于比较简单的动画,咱们能够先尝试应用原生CSS的transition\animation属性来进行实现。

简略的展现型动画+弱交互:

对于简略的动画展现并且须要有简略的交互行为,比方用户点击一下暂停执行相应操作,待操作实现持续播放动画,交互方面比拟偏弱,能够采纳Anime.js的计划。

Anime.js不仅仅反对所有的CSS属性,而且能够通过Timeline,callback, playback controls来管制动画执行的各个状态,并且Anime.js能够配合实现SVG动画。

简单的展现型动画:

  1. 如果所需的资源很小,能够先思考应用GIF动图或者逐帧动画CSS实现;
  2. 如果所需的资源较大,能够应用Lottie计划,而后设计同学用AE到处动画json,将动画还原为svg/canvas/html。

强交互&互动小游戏&骨骼动画:

  1. 对于交互场景比拟负责或者须要做一个小游戏,能够采纳PixiJs,通过WebGL来渲染,利用硬件资源,极大的晋升性能,在兼容性方面,对于不反对WebGL的浏览器,能够应用canvas渲染来安稳回退;
  2. 如果是须要展现骨骼动画,能够通过PixiJs计划进行渲染由Spine或DragonBones输入的文件。