基于web技术的高性能动画

 开门见山地来讲,现代浏览器在position(定位)、scale(伸缩)、rotation(转换角度)与opacity(透明度)这四个属性运行动画的成本是很低的。如果你进行其他方面的动画,那就看你的运气能不能看到60FPS的平滑运动效果。

此处省去N个字与YOUTUBE视频……(注:可以爬墙的同学可以去看看这个视频,该视频是CSS 动画中达到相同效果分别采用 top/left 与transform 对比的慢放模式。结果是:采用transform方式能够在指定的时间顺利完成,其他的却没有,这是为什么呢?)

DevTools中,从DOM结构到像素级别的分析

如果你用Chrome DevTools 的 timeline,你可能会看到与这类似的模式:

chrome DevTools的帧模式 ,你运行的瀑布式线图越高,表明你的浏览器工作得越多

 浏览器运行上图的过程还是相当简单的:计算应用到DOM元素的新样式(重新计算),生成几何形状(box盒模型)与为每个元素定位(layout布局),然后为每个元素填充像素插入layers(Paint setup and paint 绘制设置与绘制),最后把layers输出到屏幕(Composite layers 合成层)。

为了达到平滑的动画效果,你应该避免触发上述复杂过程,最好的方法是只改变影响到上述最后阶段compositing(合成)过程的属性——transform与opacity(注:这两个属性变化不会导致元素位置变化)。在timeline 上的 瀑布式线图越高,浏览器就要做更多的工作来获得DOM元素的像素值来展现在屏幕。

建议要考虑各个浏览器兼容性。Chrome, Firefox, Safari and Opera都可以支持开启硬件来加速 transform与opacity。不幸的是,对于符合标准的IE10+是否开启硬件加速尚不可知,但起码不令人沮丧的是IE11的F12工具的到来是比较明确的。

----Paul Irish

布局属性的动画

当你改变元素,浏览器可能就需要做一次布局动作,导致浏览器计算受改变影响的所有元素的几何形状(包括位置与大小)。如果你改变一个元素,其他元素的几何形状(包括位置与大小)也可能需要重新计算。举例来说,改变<html>这个元素的宽度,它的子元素就会受到影响。由于元素的溢出会影响其他的元素,变化会进一步沿着DOM 树向下发展,有时会导致布局计算所有变化的方式引起自下而上的重绘。

可见元素的DOM 树越大,所花费的布局计算时间越长,所以你必须牢记勿用避免触发布局变化的动画属性。

你是否在元素或者其class里面保存应用的某些状态。当这些元素变化的时候,浏览器可能不得不再次进行样式计算与布局。注意在应用中那些不慎触发布局变化的地方,他们可能不会产生动画,但其代价却是昂贵的。

 ----Paul Lewis 

这里是一份常见 的CSS属性表,如果变化,会触发布局(layout):

影响布局的样式

  • width 
  • height 
  • padding 
  • margin 
  • display 
  • border-width border 
  •  position :left、top、right、bottom
  • font-size、 font-weight、font-family
  • float 
  • text-align 
  • overflow-y  overflow   
  • line-height 
  • vertical-align  
  • clear 
  • white-space  
  • min-height

绘制属性的动画

改变布局也可能触发paniting(绘制),现代浏览器的绘制过程主要是在软件渲染层,一个元素的变化是否引起其他元素需要绘制,取决于在你的应用中这些元素是如何组织到layers。

如果你对layers的概念不了解,请阅读Tom Wiltzius的这篇文章introduction to the topic.

----Paul Irish

也有许多CSS属性能够触发paint,这是比较常见的:

Styles that affect paint

  •  color 
  • border-style 、border-radius
  • visibility 
  • background、 background-image、 background-position、background-repeat 、background-size
  • text-decoration  
  • outline-color outline outline-style  outline-width 
  • box-shadow 

如果你采用以上属性来进行动画,这(些)受影响的元素将会发生repaint(重绘),这些元素所属的layer将会上传到GPU。在移动设备上,这些消耗是特别昂贵的,因为移动设备的CPU性能明显弱于桌面设备,这就意味着他们要花费更多时间来绘制,并且CPU与GPU之间的带宽也是有限的,所以元素的质感表现也需要很长时间。

合成属性的动画

有一个CSS属性,你可能期待它发生paint,但却没有paint,这个属性就是:opacity。用一个比较低的alpha值来简单绘制元素的透明度,会触发合成层(compositing)阶段,在此过程中,opacity的变化由GPU处理。针对这个过程,要确保该元素在此层中是唯一的。如果这个元素与其他元素处在同一组中,在GPU改变该元素opacity的同时,也会错误地使同组的其他元素发生透明度的变化。

在Blink与webkit内核的浏览器中,任何元素的opacity有css transition 或者animation的属性,新层就会被创建,但是许多开发者采用translateZ(0) 或 translate3d(0,0,0)来手动触发新层的创建。创建新层要确保两方面:一是该层被绘制,随时准备着动画的启动(创建与绘制层不是常规操作,应该尽量延迟到动画启动的时候),二是表现上没有突然的变化(为了达到抗锯齿变化)。但是,还是应该尽量减少新层的增加;你可以过度来创建新层,然后会发现太多的层会导致jank现象

在chrome,非根层与有透明度的层采用灰度抗锯齿而不是完整的子像素抗锯齿,这是值得注意的,尤其是在抗锯齿方法突然改变的时候。如果你想要增加一个元素,不要等到动画启动的时候来做,而应该提前来做。

----Paul Lewis

改变元素的transform归纳起来可以改变它的position(位置)、rotation(角度)或scale(伸缩)。通常,通过设置left或者top来实现位置动画。问题就是,如上所述,left与top都会触发到布局操作,那是昂贵的代价。比较好的方式就是在元素上采用translate,这不会触发布局改变。

In Chrome Canary and Safari you can also animate filters, as these are handled off the main thread, are accelerated and generally perform very well. But since filters are not yet supported in Internet Explorer or Firefox you should proceed with caution.

驱动式动画VS声明式动画

开发者不得不考虑实现动画是采用javascript(驱动式)还是css(声明式)。每种方式都有优缺点,让我们来看一看:

驱动式

驱动式动画的主要优点也就是它主要的缺点:它运行在javascript中,浏览器的 主线程。主线程被其他javascript代码占用已经够忙了,还要进行样式计算,布局layout 与绘制painting。通常情况下,这些行为都有一个线程控制争夺的过程。这会大幅增加丢帧的机会。

javascript中的动画的确给了你许多控制权:启动(starting)、暂停(pausing)、反向(reversing)、中断(interrupting)与取消(cancelling)。一些效果,如视觉滚差( parallax scrolling)只有在javascript才能实现。

声明式

可选的方案是在CSS中写transitions与animations。最基本的好处就是浏览器能够优化动画。在必要的时候创建层,操作可以不必占用主线程,你看到这些就说明是一件好事情。CSS动画的最主要缺点是缺少javascript动画的表现力,通过一个有意义的方式合并动画是很困难的。

总结

好的动画是一个优秀网站体验的核心。你应该始终避免采用那些能够触发浏览器layout改变或者paints的CSS属性来实现动画,因为这些代价是昂贵的,也有可能导致动画跳帧。声明式动画比驱动式动画更令人青睐,因为浏览器首先可以对它们进行优化。

原文地址:http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/

作者 :Paul Lewis & Paul Irish

翻译地址:http://www.gbtags.com/gb/share/2498.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值