# 动效开发 4:逐帧动画
前一小节我们花了很大的篇幅去讲解「补间动画」的开发,除了因为它最常见,还因为其中间的许多实现思路(如「动效的审查与分解」、「基于 AE 动效稿还原动画」)同样适用于本小节将要介绍的另一种常见的基础动画形式 —— 「逐帧动画」。
# 什么是逐帧动画
逐帧动画的英文名字是 Frame-By-Frame Animation,其在维基百科中有如下定义:
定格动画,又名逐帧动画,是一种动画技术,其原理即将每帧不同的图像连续播放,从而产生动画效果。
简而言之,逐帧动画有两个要素:
(1)相关联的不同图像,即动画帧 (2)连续播放
逐帧动画最经典的例子,莫过于手翻书了。动画帧绘制在书本的不同页上,通过手动翻页来实现连续播放:


(图片来源:《一起翻一翻,手翻书的前世今生》)
# 逐帧动画的前端实现方案
在细聊 CSS3 逐帧动画之前,我们先了解下前端实现逐帧动画的几种方案。
# 1. 直接使用 GIF
GIF 可以有多个动画帧,连续播放是其自身属性,是否循环也是由其本身决定的。
GIF 往往用来实现小细节动画,成本较低、使用方便、兼容性好,但同时也存在画质低、交互不灵活等问题。
# 2. 使用 JavaScript 控制动画播放
将动画帧合并成雪碧图,放到 background-image 中,通过 JavaScript 改变 background-position 的值来实现动画的播放。
使用 JavaScript 实现逐帧动画,兼容性佳,且交互灵活。
# 3. 使用 Canvas 及相关库
将动画帧绘制到 Canvas 上,通过不断地重绘即可实现逐帧动画。CreateJS、Pixi.js 等库都提供了成熟的方案。
使用 Canvas 可以利用硬件加速,功能强大,操作灵活,有丰富的类库,但学习成本较高,且老式浏览器不兼容 Canvas。
# 4. 使用 CSS3 阶梯函数 steps(number_of_steps, direction)
CSS3 使用 animation-timing-function 的阶梯函数 steps(number_of_steps, direction) 来实现逐帧动画。
在实际工作过程中,开发「逐帧动画」最为常见的两种方式是第 3 和 4 种,CSS3 Animation 兼容性良好,相对于 JavaScript,CSS3 逐帧动画使用简单,且开发效率更高;而 Canvas 因为其性能优势,帧与帧之间切换的衔接度更高,适合实现帧数或尺寸(宽高)较大的逐帧动画。
# 案例实战 1 - 利用 CSS3 实现逐帧动画
与使用 JavaScript 实现相同,通过 CSS3 实现逐帧动画时,也是将动画帧放到 background-image 中。
逐帧动画往往有多个不同的动画帧,可以直接通过更改 background-image 的值实现帧的切换,但多个图片文件会带来多个 HTTP 请求,且不利于文件的管理。
比较妥当的做法是,将所有的动画帧合并成一张雪碧图(sprite),通过改变 background-position 的值来实现动画帧切换。因此,逐帧动画也被称为“精灵动画(sprite animation)”。
下面以京东到家的触屏页面《年货送到家》中的一个场景为例,为大家讲解如何利用 CSS3 来实现逐帧动画。

