✦✦✦✦✦✦✦✦
在手机上使用CSS动画时,经常会感到卡住。 后来网上很多教程都说开启GPU加速translate3d(0,0,0); 可以解决,但是为什么开启GPU加速就能让动画流畅呢?
让我们从浏览器内部来理解它
JS是单线程的,浏览器可以开启多线程。 渲染网页需要两个重要的线程共同完成:
主线程的工作:
运行js
估计 HTML 元素的 CSS 样式
布局页
将元素绘制到一个或多个位图中
将这种位图交给CompositorThread进行处理
概述线程的工作:
通过GPU将位图绘制到屏幕上
通知主线程更新页面可见或正式可见部分的位图
估计页面的哪些部分是可见的
估计页面滚动时页面的哪一部分正式可见
将页面滚动时对应位置的元素连接到可见区域
我们知道,如果JS长时间执行,主线程就会被阻塞,页面就会出现各种卡顿的情况。
绘图线程将尽力响应用户的交互。 当页面发生变化时css 性能,绘图线程将以每秒60帧的速度运行(60fps是最适合人眼的交互,低于30fps的动画会让人感觉明显的滞后)。 页面会每隔一定时间不断重绘。
GPU 在以下方面速度很快:
然而,将位图加载到 GPU 内存中有点慢
扯远了关于这两张图的事
div {
height: 100px;
transition: height 1s linear;
}
div:hover {
height: 200px;
}
一个从height:100px到height:200px的动画按照下面的流程图执行各种操作
图片中有太多的白框,浏览器会做大量的估计css 性能,动画就会卡住。
由于每一帧的变化,浏览器正在布局、绘制、将新的位图交给GPU内存(这恰好是我们前面提到的GPU的弱点)
虽然只是改变元素的高度,其子元素的大小很可能会同步改变,但是浏览器要重新估计布局,主线程估计完成后会重新生成元素的位图。
使用变换属性的动画
div {
transform: scale(0.5);
transition: transform 1s linear;
}
div:hover {
transform: scale(1.0);
}
流程图如下
显然,有了这么几个红框,动画肯定会很流畅。
由于transform属性不会改变自身及其周围元素的布局,因此它会影响元素的整体形状。
因此,浏览器只需要生成一次这个元素的位图,然后在动画开始时交给GPU处理他最擅长的位移、旋转、缩放等操作。 这将浏览器从执行各种布局、绘图和其他操作中解放出来。
在 Chrome 中进行比较
在浏览器中执行demo代码看看效果,demo地址:
过渡:高度1s线性
变换:缩放(1.0)
改变大小的也是缩放动画
✦✦✦✦✦✦✦✦