为什么要制作动画?
现在的营销活动,用一个很简单的图片去吸引消费者已经远远不够。想让消费者创造GMV,肯定需要让消费者觉得眼前一亮或是有视觉冲击的东西,或者在动画过程中提供更好的引导部分,比如红包,引导消费者去戳红包,他们自然而然就进入到角色当中。历年双十一手淘动画层出不穷,去年一些比较典型的动画、场景,其实也是给大家展示了一次事件; 这些提供给消费者或者用户的动画,其实就是一个入口,让他们知道手淘正在做某活动。
制作动画的方式很多,以前会让视觉设计师或动画设计师去做一个视频、GIF, FLASH。相对来说,这整个流程比较简短,因为当视觉设计师产出了视频GIF或者FLASH之后,直接把它放到网页里,或者直接拿播放器播放就可以。但它是一个已经定好的内容,没法根据不同用户的交互产生一些变化。紧接着HTML5的应用越来越广泛,可以用SVG、Canvas以及HTML5做动画,这样就会达到引导用户,或者说千人千面的效果。
动画有一些基本的组成要素,每一个元素有各自的特性,比如尺寸、位置、样式、变化(比如旋转或是缩放)等等。元素是整个动画里最基础的组成部分,有了元素以后,就把它交给引擎去渲染。因为元素本身是一个描述性结构,要让引擎把元素绘制出来。引擎的概念比较广义,可以是CSS;也可以是Canvas。有了元素以后,就需要让动画动起来,所以需要一个动效器。动效器用来描述元素的一系列的动作,包括元素的动画时长,动画是否要循环,以及缓动函数。一个动效器可作用一个元素。因为动效器的概念相对底层,因此可以基于动效器二次开发,开发一些更加接近现实、接近物理学的动画内容。比如说粒子效果,因为其随机性,近几年应用非常广泛。包括物理学上的自由落体、钟摆、视差等等,其实都跟物理学本身有关系。可以借助动效器,再借助一定的数学公式把它变成更加复杂的一段动画。
元素和动效器组合起来就叫动画。动画本身有一些特定属性,比如动画开始播放、结束播放,以及播放的状态等等。有了动画就要有时间,时间轴就应运而生。最后需要一个触发器,其实触发器的概念主要针对于程序开发。因为需要每一帧都触发一下,让时间轴跑起来,然后动画真正地开始运作。不管是哪些工具,哪些动画,它其实解决了几个问题,让元素变得简单,让描述动效变得简单,让管理动画变得简单,最终让开发整个动画变得简单。
如何制作动画?
现在简单说一下在开发模式当中怎样形成一个动画。以红包火山为例,右侧的链路是最普通的开发动画链路。首先在动画里创建一个场景,接着把需要用到的元素添加到场景里去,再接着给这个元素绑定一个动效,也就是创建出来一个动画,最终把动画播放出来,就能看到红包火山的效果。那么,每一步主要做什么呢?
首先创建场景,场景这个概念在动画里不具体指某一元素或某一具体可以被绘制的内容。当有元素被添加到场景之后,才会被渲染。否则,就算创建了这个元素,它也不会被渲染。这么做是为了在动画的整个渲染过程上节省一点成本。举个例子,红包火山动画元素将近三四十个,有些动画元素在最开始并不需要,但是在写代码时先创建了它,然后在需要用的时候把它渲染出来。这时需要有一个管理机制去识别哪一些元素,需要在什么时候被渲染,这就有一个场景的概念了。
在做红包火山动画的时候,把它归为一个场景四个片断。最开始倒计时,中间有一段火山升起,第三个是火山升起以后的火焰喷发,喷发结束,或者在喷发的同时,有红包喷发。整个红包火山就是这么一个场景。
有了场景以后,需要添加元素。首先让元素有一个形状,一般来说,元素的形状可以简单地归类为矩形、圆形、椭圆形、三角形。因为字体文本特殊一点,所以会单独拿出来。另外还有组,几个元素合在一起叫做一个组。创建完一个元素以后,用元素本身的特性,如样式、位置、变换等去描述元素。实际上,现在手淘应用到的大多数动画,基本上都是一张背景图片。因为设计出来的背景图片本身比较符合手淘的规范。现在很多动画主要借助矩形元素,并在矩形元素里贴入图片,然后把这些元素组合起来,最终变成一个动画。其他用的比较多的还有SVG动画。SVG在近几年流行程度越来越高,因为首先它在手机端的兼容性非常好;其次它可以做一些其他动画没法做到的效果,比如说从圆形变成三角形;或者通过比较复杂的路径,产生一些意想不到的变化。相对来说,SVG的能力更强大。不过目前要完成一个简单的动画,不需要SVG这种高级的动画效果。
在来看火山动画里的元素组成。火山主体是一个组,由下面四种元素组成:一是火山的后景,其余是三个火山的前景。把整个火山分成四个单独的元素,并且把这四个单独的元素变成了一个组。
在这里穿插一个知识,动画世界中的坐标系统。元素的位置就是动画里面的坐标。如上图,灰色框是个画布,把它认为手机屏幕,这时手机屏幕或者画布的中心点是坐标的原点,就是(0,0)位置。每一个元素也有其坐标,叫元素坐标。元素的坐标原点也是元素中心点(0,0)。最常用的坐标系是笛卡尔坐标系(右手坐标系),如上图所示意的,右手大拇指指向X轴,食指指向Y轴,中指指向的位置是Z轴,这些都指向X、Y轴的正方向,是标准的右手坐标系。
但是前端在写页面时,CSS里是左手坐标系。这和动画里经常遇到的坐标系不一样,所以需要熟悉不同的坐标系。比如,CSS里面X轴位移、Y轴位移一个,在动画里,X轴和Y轴的位移其实相反。有一个特别容易被忽略的是旋转,CSS里的旋转是顺时针,动画里定义的旋转是逆时针。所以,这两者坐标的差异,需要开发时做一个简单的转换,从CSS的坐标系转换到动画坐标系。
下一步要给动画创建动效,一个元素绑定一个动效以后才真正成为一个动画。动效本身会有一些具体内容,比如,当创建元素时,它的状态其实已经创建好了。这张图片多大,或者元素多大,还有动效的时长、延伸、晃动,或者循环的方式等等,都根据W3C的标准定义。最终,通过元素以及动效变成一个动画。
那么为什么把火山的整体变成一个组呢?其实火山上升时,有一个抖动效果,且前面三块岩石和火山的上升速度不一样。为达到这种效果,在这里做了一个简单的处理,让整个火山上升,同时又让前景的三块石头上升,把这个四个动画组合起来,达到了这样的效果。一开始石头不在一起,最终把所有石头拼在一起,拼成火山。把这四个元素变成一个组,让组抖动,组里面的元素也会跟着抖动。这样处理的目的是,优化性能。如果对很多元素做不同的效果,相较于对一个组做一效果,性能会变差。
把动效简单地分解一下,其实设置比较简单,包括样式、时间,以及循环等,这是动效本身的一些组成部分。
这是单个动效,有时候需要把多个动效组合在一起。比如说红包火山,一个沿Y轴移动的动效,一个沿X轴抖动的动效。把这两个动画组合在一起,就变成一个复合动画。如果再加一个Z轴的旋转,动画会更复杂。其实每个动效可以单独处理,当组合在一起,可以做很多不同的事情。
有了动画,接下去就简单了,就是播放场景里的动画,这也是整条做动画链路最简单一个方式。
如何管理动画?
通过创建场景、创建元素、创建动画、播放动画,完成了一个简短的动画。但是当做一个复杂项目,这一种方式远远不够。因为动画有先后顺序,有重叠时间,这时需要让每一段动画在合适的时间播放,所以需要一个智能的控制系统,去管理每一个动画。
红包火山升起喷发的动画做了四件事情:火山升起用时一秒;火山升起以后,火焰喷发用了0.4秒;火山升起以后同时岩浆往下流,也就是说,火焰喷发和岩浆流动同时开始,但是都在火山升起以后才执行;当火焰喷发以后,红包才开始喷发,岩浆其实一直在流动。这几段动画有一个先后顺序,也有重叠关系。
这里先简单说一下,CCS在处理这些动画时的短板,如火山升起用了1秒,紧接着让火焰柱喷发,这时,火焰柱开始喷发的时间在CSS技术里有一个delay属性,比如说延迟1秒钟,然后再让火焰柱喷发;相应地,岩浆流动也是同样的道理,也会延迟1秒钟,然后让岩浆流动。火山升起的时间,加上火焰柱喷的时间,这么长的延迟以后再分发红包,这种技术方案虽然解决了问题,但是没能提高效率。
所以在动画体系里,提出时间轴的概念。创建时间轴,并在加入一个动画,给该动画两个参数,即开始时间和结束时间。当然,这两个时间不仅仅可以用绝对时间值,还可以是状态码。正常情况下,不会关心火山升起用了多久,只关心火山升起结束的状态。相应地,火山喷发也有一个开始时间和结束时间,但后续的动画并不关心这个时间,只要知道火焰喷发结束这个状态就可以了,再继续下一个动画就可以了。CSS本身没有这样的能力,而JS就可以驾轻就熟。
如何扩展动画?
很多动画会处理成图片位移加上元素位移的形式。
比如精灵动画也叫雪碧图动画,它是很多张图片(或一张图片展示不同的位置)不断地切换轮播产生的效果,是最常用的一种手段。另外一个是路径动画,位移最直观的是一条直线,从X点到Y点;如果移动轨迹是一条很复杂的曲线,就要建立路径。路径在动画里非常普遍,要通过动效做出来复杂的动画,就要用到现实或物理中一些抽象的能力。
精灵动画可以提取出来几个关键词:一是精灵图片的地址,如上所述,这是很多张图片的拼接;二是每一帧精灵图片的尺寸;三还要知道这张图里一共有多少帧精灵图片;四是精灵图片播放的序列,因为在很多应用场景里,设计师提供了一组精灵图片,可能其中的某一个区段或者某几帧图片要重复利用,循环播放,这时必须要知道在播放整个动画时,帧序列是什么;最后就是最基本的播放参数,比如时长、延时等等。把这些内容抽象出来以后,通过插件的形式转换动效代码,就达到了最简单的扩展动画的需求。
路径动画其实一样,一般很多种方式提供路径。路径其实就是描述了一个不规则的曲线,可能是弧线、贝塞尔曲线、离散曲线等,只要给定一个路径,就可以经过参数配置,在每一个时间点计算该路径上的某一点在哪,再让该元素运动到路径的那点就可以了。扩展出的路径动画还有一些特定的效果,比如物体在移动时是否根据曲线的切线或法线进行旋转等等。
如何改进开发模式?
整个项目来看,开发动画只是其中的一小部分,只动用了前端这一个技术层面,但是做整个项目的时候,有PD、视觉、运营、市场、前端技术等等。所以真的要完成一个动画,开发模式应该怎样做呢?
手淘早期开发动画的时候,简单粗暴,视觉提供设计稿,可能是一个视频、GIF或FLASH,前端用眼睛识别这个动画,用CSS或其他技术还原。视觉会定期检查说动画跑得不对,少两个象素等。这样,每一个动画开发下来,抛开业务层面,光开发动画就可能会花掉整个项目周期70%-80%的时间。所以在做一个项目时,整个时间的比例非常不协调,同时也造成前端的返工比较严重。效率非常低,成本却非常非常高。
现在开发动画会借助整个工程体系的能力,比如视觉通过某一类编辑器,这些动画编辑器需要遵循规范的结构描述语言,就是一段结构化数据,然后用播放器把结构化描述语言播放出来。这时,最简单的动画根本不需要业务开发,设计师只要完成动画的设计稿,一连串的系列都不需要前端介入。最终的交付其实就是从视觉开发完以后,直接用命令变成一个结构化的描述语言,最后把它发布到线上的播放器就可以了。假如有一些业务逻辑,这时基于结构描述语言,把它转换成业务描述语言。二者可以互相转换,当通过编辑器导出结构化描述语言以后,把它变成业务描述语言;在其之上添加一些业务逻辑,最后再转换成结构描述语言,让播放器播放。最后会发现,前端能够通过这样的开发方式,可以不参与动画本身制作,只关心业务,整个动画周期几乎可以并行。