CSS3动画和js动画各有什么优劣
在msdnCSS动画页面有这样一句话:
与传统的 JavaScript 驱动的动画实践比较,它可提供更好的呈现性能。
出自: http://msdn.microsoft.com/zh-cn/library/jj680076(v=vs.85).aspx
移动端的开发也有这种hack,来解决可能的卡顿问题:
css-webkit-transform: translate3d(0, 0, 0);
出自: http://www.qianduan.net/high-performance-css3-animations.html
看了一些文章,介绍CSS3动画的会说道一些性能问题,但没有具体说清楚,这这两种动画在开发中(包括移动端)如何取舍呢?
Answers
css3可以很便捷的实现一些动画效果,并且在支持css3的浏览器下表现不错,用js做动画的话,除非是在非常古老的浏览器(你懂的)下运行,一般也不会有卡顿问题,不过还是建议在支持css3的浏览器下使用css3去做动画。移动端的话,其实能用的效果真的不多,以前做过一个折叠效果,在安卓下完全不堪入目,IOS下也是勉强看到折了那么一下,但是pc上看就很顺畅,一般的滑动效果还是没有问题的,而且相当顺畅。
总结下,工作中如果要兼容那些老古董的话,还是用js去写动画,如果只需要兼容现代浏览器的,尽量使用css3做动画,移动端就完全不要考虑js写动画了。
根据
Google Developer
,Chromium项目里,渲染线程分为main thread和compositor thread。
如果CSS动画只是改变
transforms
和
opacity
,这时整个CSS动画得以在compositor thread完成(而JS动画则会在main thread执行,然后触发compositor进行下一步操作)
在JS执行一些昂贵的任务时,main thread繁忙,CSS动画由于使用了compositor thread可以保持流畅。
在主线程中,维护了一棵Layer树(LayerTreeHost),管理了TiledLayer,在compositor thread,维护了同样一颗LayerTreeHostImpl,管理了LayerImpl,这两棵树的内容是拷贝关系。因此可以彼此不干扰,当Javascript在main thread操作LayerTreeHost的同时,compositor thread可以用LayerTreeHostImpl做渲染。当Javascript繁忙导致主线程卡住时,合成到屏幕的过程也是流畅的。
为了实现防假死,鼠标键盘消息会被首先分发到compositor thread,然后再到main thread。这样,当main thread繁忙时,compositor thread还是能够响应一部分消息,例如,鼠标滚动时,加入main thread繁忙,compositor thread也会处理滚动消息,滚动已经被提交的页面部分(未被提交的部分将被刷白)。
CSS动画比JS流畅的前提:
- 在Chromium基础上的浏览器中
- JS在执行一些昂贵的任务
-
同时CSS动画不触发layout或paint
在CSS动画或JS动画触发了paint或layout时,需要main thread进行Layer树的重计算,这时CSS动画或JS动画都会阻塞后续操作。
参考 CSS Triggers ,只有如下属性的修改才符合“仅触发Composite,不触发layout或paint”:
- backface-visibility
- opacity
- perspective
- perspective-origin
- transfrom
所以只有用上了3D加速或修改opacity时,才有机会用得上CSS动画的这一优势。
因此,在大部分应用场景下,效率角度更值得关注的还是下列问题。
- 是否导致layout
- repaint的面积
- 是否是有高消耗的属性(css shadow等)
- 是否启用硬件加速
那么Chromium以外的其他浏览器呢?CSSTrick里 比较了一次效率 。
Animated properties | JS-based Animation更快 | CSS-based Animation更快 |
top, left, width, height | Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS 6), iPad 3 (iOS7), Samsung Galaxy Tab 2, Chrome, Firefox, Safari, Opera, Kindle Fire HD, IE11 | (none) |
translate, scale | Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS7), Samsung Galaxy Tab 2, Firefox, Opera, IE11 | iPad 3 (iOS6), Safari, Chrome |
可以看到,Chromium以外的其他浏览器没有这方面的CSS动画效率的优化。尽管MSDN提到“它可提供更好的呈现性能”,但测试并没有支持这一点。
现今CSS动画和JS动画主要的不同点是
-
功能涵盖面,JS比CSS3大
-
定义动画过程的
@keyframes
不支持递归定义,如果有多种类似的动画过程,需要调节多个参数来生成的话,将会有很大的冗余(比如jQuery Mobile的动画方案),而JS则天然可以以一套函数实现多个不同的动画过程 -
时间尺度上,
@keyframes
的动画粒度粗,而JS的动画粒度控制可以很细 - CSS3动画里被支持的时间函数非常少,不够灵活
- 以现有的接口,CSS3动画无法做到支持两个以上的状态转化
-
定义动画过程的
- 实现/重构难度不一,CSS3比JS更简单,性能调优方向固定
- 对于帧速表现不好的低版本浏览器,CSS3可以做到自然降级,而JS则需要撰写额外代码
-
CSS动画有天然事件支持(
TransitionEnd
、AnimationEnd
,但是它们都需要针对浏览器加前缀),JS则需要自己写事件 - CSS3有兼容性问题,而JS大多时候没有兼容性问题
有段时间没上SF了...才看到
CSS3的动画的优点:
- 在性能上会稍微好一些,浏览器会对CSS3的动画做一些优化(比如专门新建一个图层用来跑动画)
- 代码相对简单
但其缺点也很明显:
- 在动画控制上不够灵活
- 兼容性不好
- 部分动画功能无法实现(如滚动动画,视差滚动等)
JavaScript的动画正好弥补了这两个缺点,控制能力很强,可以单帧的控制、变换,同时写得好完全可以兼容IE6,并且功能强大。但想想CSS动画的transform矩阵是C++级的计算,必然要比javascript级的计算要快。另外对库的依赖也是一个很让人头疼的问题。
所以,对于一些复杂控制的动画,使用javascript会比较靠谱。而在实现一些小的交互动效的时候,就多考虑考虑CSS吧