若干星期前,承玉 心痒痒的推荐了一篇文章:Using CSS3 Transitions, Transforms and Animation.

我也心痒痒,但没啥时间。于是撮合 龚浩 一起折腾 S.Anim. 若干天的努力,终于有了成果,小结下。

原理

所谓动画,就是在一段时间内,连续改变 DOM 元素的属性。

因此用 JavaScript 实现动画,最传统的方法就是采用定时器,在一段时间内(duration 时长),遵循特定规律(easing 平滑函数),改变 DOM 元素的属性(props, 最常见的是 style),在动画结束时,触发回调(callback)。一个典型的接口如下:

var anim = new Anim(elem, props, duration, easing, callback);
anim.run();

有了 CSS3 Transitions 之后,传统方法中的定时器变得多余,我们只要:

elem.style.transition = 'props duration time-function';
elem.style.cssText += ';' + targetStyle;

这样,就能调用浏览器原生的 transitions 将元素从当前样式逐步过渡到最终样式,这就是动画!

实现

上面仅是原理说明,真实代码(anim.js)复杂些,有两点值得记录:

1. 能自动检测是否支持 CSS3 Transitions. 仅在支持时,才调用(优雅降级)。请参考源码中的 getNativeTransitionName.

2. 平滑函数 (easing-function) 在 CSS3 Transitions 中叫时间函数 (timing-function). CSS3 的时间函数默认仅支持最基本的几种,对于 easingOutStrong 等平滑函数,需要用 cubic bezier 等价模拟,看这里 cubic-bezier-timing-function.html 以及源码 anim-easing.js.

真正麻烦的是 elastic 等平滑函数,这些函数无法简单用 cubic bezier 模拟。如果要用 CSS3 Transitions, 得分拆成多个 transitions, 组合起来才能实现。考虑到不常用性和麻烦性,对这些默认不支持的平滑效果,依旧直接降级到传统定时器方式。

其他细节,建议阅读源码。

性能

折腾上面这些,最直接的一个起因是 S.Switchable 中,龚浩写过一个倒计时效果插件(demo, 淘宝首页卡盘数字切换点的背景倒计时效果)。这个效果很不错,但在 Firefox 等浏览器下 CPU 占用比较高,导致最后没上线。

这次改用 CSS3 Transitions 来实现,性能有非常明显的改善,看下面的例子。

测试

请猛击数字爆米花效果:popnum.html. 记得看完动画哦,最后有杯具:)

在我的老而弥坚的 T61 本本上,Chrome 6 下,开启和关闭 (加 off 参数访问:popum.html?off) native transition 时的 CPU 占用率:

CPU 占用率差了一倍多。

同样可以对比测试 jQuery / YUI3 等类库实现的动画。目前为止,在高级浏览器下,KISSY 的优势非常明显。

结语

除了 CSS3 Transitions, 还有 CSS3 Transforms 等等新特性等待我们去探索。
KISSY 团队相信:只要敢想,努力去做,就会有超越与创新。

最后,感谢你的阅读。非常期待你的试用、建议和参与。