performance面板使用,以及解决动画卡顿
https://googlechrome.github.io/devtools-samples/jank// 官方案例
https://juejin.im/post/5b65105f5188251b134e9778
https://juejin.im/post/5b6d45216fb9a04fe91aa733
The Anatomy of a Frame https://aerotwist.com/blog/the-anatomy-of-a-frame/
http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html 浏览器渲染过程
https://juejin.im/post/5bd947326fb9a0226924ad77 CSS动画的性能分析和浏览器GPU加速
https://blog.csdn.net/leer168/article/details/25917093 深入浏览器理解CSS animations 和 transitions的性能问题
https://blog.csdn.net/weixin_34252090/article/details/89275051 说说动画卡顿的解决方案
实际案例
https://juejin.im/post/5a6e78abf265da3e3f4cf085
https://juejin.im/post/5b879e16f265da436d7e543c
遵循的原则
1. 关于阻塞
- css加载 不会阻塞 DOM树的解析;CSS解析 会阻塞;
- css加载和解析 会阻塞 js(所以内联样式不用加载性能较高,适用于第一屏)
- js 会阻塞 DOM树的解析 (因为js会改变DOM树内容)
- css引入的字体文件加载 也会阻塞 js , 页面渲染
2. 关于与页面渲染过程的对应
- js执行时:这时应该只是构建了前面部分的dom树和CSSOM树,因为js需要通过dom api和CSSOM api操作前面部分的标签的内容和样式。
- DOM树构建完成:DomContentLoaded事件
- CSSOM构建完成、Render Tree构建完成:Recalculate Style
- Layout:Layout事件
- paint:Paint(图片层绘制) 和 Composite Layers(图片层合并),除了transform 或 opacity属性之外,更改任何属性始终都会触发绘制Paint。
- reflow重排:3 4 5步走一遍
- repaint重绘:3 5步走一遍
- 更改一个既不要布局也不要绘制的属性:3步 + Composite Layers,此行为在678重新渲染步骤中开销最小,适合动画或滚动,具体比如transfrom opacity。
3. 关于chrom浏览器的一些行为
- 渲染队列:浏览器存在一个渲染队列,用于将多次连续的重排和重绘操作变成一次。当你进行DOM的读操作时,如果队列不为空,chrome会清空队列,立即进行重排或重绘;如果为空,chrome不会做出多余的操作。
- 布局:布局或重排中浏览器需要计算元素要占据的空间大小及其在屏幕的位置,网页的布局模式意味着一个元素可能影响其他元素,例如
<body>
元素的宽度一般会影响其子元素的宽度以及树中各处的节点。 - 绘制与合成:绘制一般是在多个表面(通常称为层)上完成的,因此浏览器需要将它们按正确顺序绘制到屏幕上,以便正确渲染页面。
- css选择器:对于复杂的css选择器,浏览器需要花更多时间来确定元素的样式,因此以类为中心的css编写原则,老外比较推崇,比如:nth-last-child伪类可以用独立的类替代(不然它怎么叫伪类( ̄▽ ̄)")。
手动控制重新渲染
window.requestAnimationFrame() 方法可以将某些代码统一放到下一次重新渲染时执行。具体是将js代码放在下一帧开始时执行。如果使用setTimeout 或 setInterval 来执行动画之类的视觉变化,其回调可能在帧的某个时间点执行,可能在末尾,这会使我们丢失帧,导致卡顿。
- 处理“布局抖动” 反复读写属性会导致布局抖动,导致长帧。
function doubleHeight(element) {
var currentHeight = element.clientWidth;
element.style.width = (currentHeight / 2) + 'px';
element.style.height = '80px';
}
var elements = document.getElementsByTagName('tr');
for (var i = 0; i < elements.length; i++) {
doubleHeight(elements[i]);
}
将doubleHeight函数改成下面这样:
function doubleHeight(element) {
var currentHeight = element.clientHeight;
window.requestAnimationFrame(function () {
element.style.height = (currentHeight * 2) + 'px';
});
}
2)页面滚动事件(scroll)
$(window).on('scroll', function() {
window.requestAnimationFrame(scrollHandler);
});
3)最适合用于动画