CSS3实现逐帧动画

随着浏览器对于css3的兼容,css3实现的动画也登上了前端的舞台,甚至在性能上已经超过了原来使用js实现动画的性能,那么,如何使用css3更加优雅地实现动画呢?

前言

动画的类型有很多,位移、旋转、放大缩小等等,这些都属于比较基础的动画,对于一些比较复杂的动画,可能就需要使用逐帧的方式进行实现。

逐帧动画

什么是逐帧动画?逐帧动画就是把一个完整动画分成很多张静态图,然后这些静态图接连播放就是一个完整的动画,这对于flash开发的同学可能再熟悉不过了。

js版本实现逐帧动画

对于web技术实现逐帧动画来说很简单,就是使用精灵图,将所有帧动画拼接成一张精灵图,然后改变background-position就可以了,自然,对于JS来说,只需要设置一个interval函数,然后每次获取当前background-position值,然后用当前的background-position减去帧动画的宽度就好了。

css3的animation

对于如何使用css3实现逐帧动画,自然,大家都想到了animation,因为配合keyframes可以实现不同阶段的变化,最简单的思路,我现在有一个5帧的动画,精灵图的宽度为100px,每帧的宽度为20px,from to的实现方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
@keyframes toggle {
from {
background-position: 0 0;
}
to {
background-position: -100px 0;
}
}

.animate{
animation: toggle 1.2s liner;
}

这样的话是有问题的,因为帧动画讲究的是分帧显示,而不是连续显示,也就是说一帧显示完要跳到下一帧。好,那么大家说那我用阶段百分比实现呢?代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@keyframes toggle {
0%{
background-position: 0 0;
}
20%{
background-position: -20px 0;
}
40%{
background-position: -40px 0;
}
60%{
background-position: -60px 0;
}
80%{
background-position: -80px 0;
}
100%{
background-position: -100px 0;
}
}

.animate{
animation: toggle 1.2s liner;
}

这样的话,其实跟from to实现没啥区别,其实问题不是出在是否需要定义分阶段的动画,而是需要关注animation的animation-timing-function这一个参数,也就是上面代码中的”liner”,”liner”是指线性实现动画,但是跟我们的逐帧还是有点区别,但很接近了,继续查文档,然后发现animation-timing-function还有一个steps函数,然后我们将代码稍微修改下:

1
2
3
4
5
6
7
8
9
10
11
12
@keyframes toggle {
0%{
background-position: 0 0;
}
100%{
background-position: -100px 0;
}
}

.animate{
animation: toggle 1.2s steps(5);
}

运行发现,效果出来了,动画不再是一像素一像素线性变化,而是逐帧变化了。

animation的steps

通过此图来理解steps会更加容易理解:
动画
animation中的steps正如它名字一样,是分步来处理动画的,这个函数接受2个参数:
第一个参数为变化的次数,也就是整个动画分多少步来跳跃实现,像上图所示,整个动画是分5步(1->6)就可以显示完全,每帧20px,所以动画不是每px线性位移,而是每20px位移。
第二个参数可设置为”start”和”end”两个参数,默认是”end”,网上的解释有很多,官方解释是”指定在每个间隔的起点或是终点发生阶跃变化”,是不是有点云里雾里的感觉,其实最通俗的理解就是,如果你设置start的话,你相当于丢弃了0%的那帧(上图箭头1)直接进入到第二帧(上图箭头2),如果你设置为end或者不设置(默认为end)的话,那么相当于丢弃了100%那帧(上图箭头6)。所以对于上图,如果设置start的话就是从2->6,如果设置end或者使用默认值的话就是1->5。对于上图来说,为什么不设置第二个参数或者说使用默认的end就正常呢,因为我们会发现100%那帧(箭头6)其实是空白的背景,因为整个精灵图都跑到了屏幕的左边(-100%),这一帧对于我们来说其实是可无的(此时动画为空白),如果你一定要显示,可以设置steps(6)来进行显示。所以,这个参数表示你是要舍弃0%还是要舍弃100%,如果都不想舍弃,那么第一个参数设置为帧长+1就可以了。

结语

帧动画实现就是这么简单,但是需要注意兼容性,所以到底是用js实现还是用css3实现,就要看场合了。