欢迎移步个人博客阅读:《实用的 CSS — 动画性能对比》css
在现代浏览器中,渲染页面所要负责的线程主要有两个:主线程和排版线程。html
运行 JScss3
计算 HTML 元素的 CSS 样式web
布局页面浏览器
把页面元素绘制成一个或多个位图布局
把这些位图移交给排版线程性能
在浏览器开始渲染页面,或者长时间执行某个 JS 时,主线程会一直在忙碌状态,此时对于用户的任何输入或是操做都不会有所响应。动画
经过 GPU 渲染位图,并显示在屏幕上spa
向主线程请求更新位图的可见部分或即将可见的部分线程
判断出当前页面处于可见的部分
判断出即将经过页面滚动而可见的部分
随着用户滚动页面来移动这些部分
排版线程对于用户的操做保持快速的响应,广泛的效率时每秒 60 帧的速度去刷新显示。
下面咱们在网页中实现一个元素的高度变化的动画,鼠标悬浮在元素上动画启动,直至完成:
<style> #foo { height: 100px; width: 100px; background: red; transition: height 1s linear; } #foo:hover { height: 200px; } </style> <body> <div id="foo"></div> </body>
经过对上述代码的观察,让咱们来了解一下浏览器的两个线程是如何协同工做的:
图中橘黄色部分表明操做相对较慢,消耗较大;蓝色部分表明操做相对较快,消耗较小
从上图咱们能够看到,浏览器的两个线程在来回地切换工做,并且橘黄色出现次数较多,这意味着浏览器须要处理至关多的工做。
对于浏览器而言,因为元素的高度一直在变化,所以这个动画的每一帧中,都须要从新布局 ——> 绘制页面 ——> 将新的位图加载到 GPU 中 ——> 显示。而其中加载到 GPU
是一个相对缓慢的操做。
同时咱们也在经过浏览器去查看元素动画的过程,实际上是由略微卡顿的现象的。
通过上面的实验,咱们对 transition
属性有了比较好的了解;同时咱们对上述动画性能也有一个了解。接着我须要在网页中实现一个元素的大小变化动画,鼠标悬浮在元素上动画启动,直至完成:
<style> #bar { height: 100px; width: 100px; background: red; transition: transform 1s linear; } #bar:hover { transform: scale(2); } </style> <body> <div id="bar"></div> </body>
完成上述实验,再让咱们来看看两个线程工做的过程:
由此咱们能够看到,两个线程来回切换的状况并很少,橘黄色部分出现的次数也较少,蓝色部分居绝大部分,这意味着这个动画效果相较于上面的要流畅不少。
在定义中,transform
是不会使浏览器产生从新排版的,所以 transform
不会影响本来的布局,以及周围的元素。它会将定义的元素做为一个总体进行缩放、移动或旋转等。
基于 transform
这类的特性,浏览器在渲染页面时能够节省不少没必要要的开支,例如从新布局和将位图传给 GPU 等工做,这样就使得动画更有效率。
当页面须要位移动画时,咱们有两种方案:使用 position
或是 transalte
,而这两种是符合上述状况的。其中 position
的位移方案与第一个符合,在动画执行过程当中会使浏览器从新渲染;另外一外 transalte
则与第二个符合,在执行动画时不会发生从新渲染。所以,在须要写动画时,咱们须要选择合适的方案,最好是选择 scale()
、rotate()
、transalte()
等,由于他们具备更好的性能。
W3C: CSS Transforms
W3C: CSS Transitions
css-animations-and-transitions-performance