H5

当你拿到一个 H5 制作的需求的时候,你需要首先明确需求的目的是什么?按照目的大概可以分为活动营销,产品宣传,会议邀请,品牌推广,企业招聘等。不同类别的 H5 有其自身的特点,但找准业务方的目的,就能抓住主题而不会跑题了。
接下来就是围绕这个主题思考创意。创意很多是来自于营销策略,方法以及对于人性的把握,这些偏软性的思考方式,我们先不讨论,作为一个程序员,我首先想到的就是怎么通过技术带来创意。

在此之前,我们先来看看制作一款 H5 有哪些「术」。

国内比较成熟的 H5 制作平台有:

  • 兔展:设计感和创意感最强的平台,但是制作相对复杂,需要设计基础。
  • 易企秀:老牌的 H5 制作平台,不断迭代,有大量案例,使用别人做好的 H5 需要付费。生态圈还不错。
  • 初页:手机 APP,手机端快速制作 H5 。适合个人用户快速制作。
  • Epub360 意派:面向设计师,提供了很多创意的设计元素和案例。

易企秀 H5 制作后台

这些平台都可以让用户通过简单的拖拽来制作一个精美的 H5 ,这种打包预设好一些动画模式的方式,非常像我们前端开发中的组件化思维,他们将元素和数据分离,用数据模型来描述元素的位置和运动,同时开发出一套动画引擎,只要将模型数据输入,就能呈现出精美的动画。

我觉得这些平台非常合适的 WEB 动画的学习,深入探究其动画的实现思路,可以让我们快速的梳理出「动画」和「 WEB 动画技术」。

WEB 动画技术

简单动画

  • 移动 (水平,垂直)
  • 旋转
  • 缩放 (放大,缩小)
  • 样式属性

身体的位移,骨骼的旋转,瞳孔的缩放,这些都是最基本的运动方式,样式的变化,则是元素自身属性的变化,例如颜色,边框,背景等,这写也是大部分动画编程最基本的要素。你完全可以使用 CSS3 来实现他。我们知道一个动画要包含,元素变化。CSS3 基于 DOM 元素,借助动画三剑客 Transition (过渡) Transform(变形) Translate (移动),实现变化。有一个非常好用的 CSS 动画库 —— Animate.css ,他预设了很多实用的动画模版,你只要在 DOM 节点上添加响应的 class 就可以了。

他们即简单又复杂,复杂在于这些运动的方式和速度、时间的结合诞生出了速度曲线,然而大自然中大多数的速度曲线来自于重力加速度 G ,由于他的存在,物体的运动不像真空中那种匀速直线的单调乏味。而充满了生机。

尤其是当你在做动画的时候,为什么你做出的动画显得非常的生硬,让人看着不舒服,其实人早已习惯了大自然的动画方式,人对每一帧动画都有稳定的预期,当你的动画与现实物体的运动脱节,就会变得生硬。

基于上述简单动画催生了一种人体动画的形式---叫做「骨骼动画」。

复杂动画

DragonBones 骨骼动画软件操作界面

我们以 DragonBones 为例,我们发现下面的有一部分,操作栏是「时间轴」,他可以描述我们每一帧动画的状态,这里其实出现了两种与时间相关的动画形式。

  • 逐帧动画
  • 关键帧动画

作为一个前端工程师,我们在做动画的时候往往不会去写每一帧的动画的状态,而是先去定义起始状态和中间动画的过渡方式,例如速度如何变化,路径如何变化。这是一种关键帧动画,在 CSS3 中我们可以用 Animation 中的Keyframes 来实现关键帧动画,Keyframes 来定义关键帧的状态,Animation 来定义时间和速度变化。

而对于逐帧动画,则明显不是 CSS3 的强项,这里就要引出更为强大的武器 —— Canvas 了。

逐帧动画

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

进入 Pixi 的世界,我们欣喜若狂,终于可以实现像素级别的动画了,Pixi 提供的强大滤镜,也让我们实现很多特效变得非常简单,然而作为一个渲染引擎,他很好的做到了高性能,而忽略了易用性,学习成本比较高,API比较复杂,尤其是逐帧动画的编码方式似乎有点反常识,或者说写起来并不是那么顺畅,而关键帧动画似乎更符合我们的编程习惯,毕竟 CSS 动画,我们烂熟于心。

那怎么用 Canvas 实现关键帧动画呢?我们为了实现某种目的,首先应该找的是方法,而方法往往已经被前人总结好,放在了你的面前,这里我们来聊两个框架: CreateJSGreenSock

关键帧动画

CreateJS 和 GreenSock 都是基于 HTML5 的一套模块化的库和工具。不仅可以实现 Canvas 动画,也支持 DOM 动画,DOM动画的原理依然是基于 CSS3 的,由于 CSS 动画三剑客并不会引起浏览器页面内容的重排和重绘,甚至还可以开启 GPU 加速,性能比直接操作 DOM 的 width、left、margin 等属性要高的多。

其实 CSS 动画和 Canvas 动画的性能到底哪个更好,并不能一概而论,这个依赖于你具体使用的场景和浏览器类型,具体的性能比较可以看 这里 ,而我认为促使我们选择 Canvas 来做动画的一个关键点在于两者明显不同的思考方式。

  • 我们把动画的主体叫做元素,在 DOM 上,元素是按照经典的「盒子模型」做组装和布局的,盒子模型天然具有父子关系和相对位置。当我们实现一些局部动画的时候,是非常方便的。
  • Canvas 并没有盒子的概念,他只有一个画布标签,而这张画布被称为舞台,舞台上任何的元素都可以自由的运动,这更像真实世界的运作方式。
  • 这两种思考方式可能正是UI设计师和前端工程师,在工作时的差异。当我们用前端的「盒子」思维开发一个拖拽式页面工具让设计师来用的时候,你就天然的在要求他们用自己不熟悉的方式去思考,画画和设计他们只有一张画板,他们先打上均匀的格子,然后找准方位,一气呵成,他们在意的是整理的美观性。

话说回来,我们来看看,关键帧动画基本的实现形式是怎样的?CreateJS 中有一个专门实现关键帧动画的库——TweenJS,而 GreenSock 中也有同样功能的库—— TimelineMax。

// TweenJS 的 API
createjs.Tween.get(circle, { loop: true })
  .to({ x: 400 }, 1000, createjs.Ease.getPowInOut(4))
  .to({ alpha: 0, y: 175 }, 500, createjs.Ease.getPowInOut(2))
  .to({ alpha: 0, y: 225 }, 100)
  .to({ alpha: 1, y: 200 }, 500, createjs.Ease.getPowInOut(2))
  .to({ x: 100 }, 800, createjs.Ease.getPowInOut(2));

// TimelineMax 的 API
var tl = new TimelineMax();
tl.to(element, 1, {left:100}).to(element, 1, {top:50}).to(element, 1, {opacity:0});

我们可以看到,两者 API 非常的相似,都采用了链式调用的方式,定义每一个关键帧和时间,以及非常关键的运动曲线,区别在于 TweenJS 专注单个元素的运动,TimelineMax 更关注在一个时间线上,不同元素的运动。

相比而言,对于动画的实现上,GreenSock 借鉴了很多 Flash 的实现方式,插件非常多,功能更全,效果更炫。其实当我们在选择一门动画框架的时候,切记不要贪多,在满足需求的基础上,深入去研究一种框架,达到熟练,才能做出更好的效果和创意。我一直认为,创新是建立在丰富的知识储备和见识之上的自然涌现,尤其要求对技术的深度,如果一直在尝试不同的框架,就只能不停的学习各种 API ,而忘记了动画的本质并不是技术,而是好的创意。

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

柔性动画

从上图可以看出,元素之间是可以相互变化的,而且非常的流畅,这样的动画并不需要 Canvas 这种重武器,简单的 DOM 就可以实现,SVG 真的是一个神器,不仅在实现图标,字体上特点鲜明,在实现柔性动画方面也独树一帜。SVG 依然是 DOM ,他有自己独有的 Animation 标签,但也支持 CSS 的属性,其实现动画的本质是依赖于线条填充,线条的变化,导致填充区域的改变,从而引起形状的变化。而线条则依赖于路径锚点,路径和锚点的改变,直接影响了线条的变化。

上面的案例,使用的是 GreenSock 的 SVG 动画插件 —— MorphSvgPlugin ,他可以实现不同 SVG 元素之间的相互转换,过渡非常平滑。

SVG 实现的动画比较局部和小巧,使用范围也比较狭窄,但是当我们实现复杂的柔性动画,甚至游戏的时候,就还是需要用 Canvas 来实现。

从上图我们可以看到龙的翅膀是一张图片,但是可以通过图片的局部的扭曲和变形,来实现煽动翅膀时带来的肌肉收缩和舒张。这样的动画是怎么实现的呢?这就要引出骨骼动画中,一个非常重要的概念:网格

这里我们比较浅显的讨论下这个概念,要实现图片的局部变化,我们就要把图片分块,分的每一块就称为网格,每个网格都有自己的顶点和边,顶点的位移会引起网格形状的变化,形状的变化就会带来所附属的图片的变化。网格的概念是不是很像路径和锚点,不论怎样的技术,在实现逻辑上都大同小异,重要的不是一直盯着不同和变化的部分,而是发现那些不变的地方,才能达到触类旁通的效果。

制作这样的动画并不复杂,你可以使用类似 Spine 和 DragonBones 这样的工具,但是做动画真的是一个体力活,你需要不断的调试,以求达到一种让人看起来舒服的状态。

总结

在大前端概念下,WEB 动画是一个非常绚烂又深邃的领域,甚至不只局限于前端,他更注重用户的交互体验,以及真实世界的虚拟化。这里我们也只讨论了这座大山的冰山一角,还有很多动画形式需要进一步研究和思考,例如:

  • 粒子动画
  • 特效动画
  • 3D动画
  • 数据可视化动画

...

当我们更深入研究,就会发现,数学的重要性,审美的重要性,创意的重要性。技术只是工具,他所涌现出来的是一种对于美的追求和体验。虽然说的不明觉厉,但是真的值得好好思考一下。

参考

03-05 23:46