zoukankan      html  css  js  c++  java
  • 图层 & 重排 & 重绘

    图层 & 重排 & 重绘

     

    图层

    浏览器在渲染一个页面时,会将页面分为很多个图层,图层有大有小,每个图层上有一个或多个节点

    渲染 DOM 时 浏览器所做的:

    • 获取 DOM 后分割为多个图层
    • 对每个图层的节点计算样式结果 (Recalculate style--样式重计算)
    • 为每个节点生成图形和位置 (Layout--重排,回流)
    • 将每个节点绘制填充到图层位图中 (Paint--重绘)
    • 图层作为纹理上传至 GPU
    • 符合多个图层到页面上生成最终屏幕图像 (Composite Layers--图层重组)

    图层创建条件

    Chrome 中满足 以下任意情况 就会创建图层:

    拥有 3D 变换的 css 属性 transform

    加速视频解码的 <video> 节点

     <canvas> 且浏览器硬件加速

    css3 动画节点 animation

    拥有 css 加速属性的元素 (will-change: transform; 记得取消为 auto )

    重绘(Repaint)

    指的是 一个元素外观的改变 而触发的浏览器行为

    例如改变 outline、背景色等属性。浏览器会根据元素的新属性重新绘制

    浏览器会根据元素的新属性对元素进行重新绘制,使元素呈现新的外观

    重绘 不会伴随 重排,但是 重排 一定会 重绘

    以图层为单位,如果图层中某个元素需要重绘,那么整个图层都需要重绘

    重排(Reflow)

    渲染对象 在创建完成并添加到渲染树时,并不包含位置和大小信息。计算这些值,称之为 重排

    resize 时、修改网页默认字体时,操作 DOM 节点时,修改 css 样式时

    获取某些属性时(width、height... ...)

    优化方案:

    减少 计算需要被加载到节点上的样式结果(Recalculate style--样式重计算)

    减少 为每个节点生成图形和位置(Layout--回流和重布局)

    减少 将每个节点填充到图层中(Paint Setup和Paint--重绘)

    减少 组合图层到页面上(Composite Layers--图层重组)

    元素位置的改变 使用 transform

    使用 opacity + will-change: transform; 代替 visibility        单独使用 opacity 会重排、重绘; 结合图层后只会发生重绘

    不使用  table 布局

    将多次 css 操作,集合成一次 css 操作

    多使用 class 修改样式

    使用 display: none; 离线 DOM 元素,在一顿 css 操作以后,再 display: block 显示;

    (vue 底层就是使用 documentFragment 来优化的)使用文档碎片 documentFragment 

    不要把某些 DOM 节点的属性 在循环里作为变量使用

    给要动的元素,单独开一个图层

    总结:

    Reflow 的成本比 Repaint 的成本高得多的多。DOM Tree 里的每个结点都会有 reflow 方法

    一个结点的 reflow 很有可能导致子结点,甚至父点以及同级结点的 reflow。

    在一些高性能的电脑上也许还没什么,但是如果 reflow 发生在手机上,那么这个过程是非常痛苦和耗电的。

    requestAnimationFrame

    •  
      <!DOCTYPE html>
      <html>
          <head>
              <meta charset="UTF-8" />
              <title>requestAnimationFrame</title>
              
              <style rel="stylesheet" type="text/css">
                  body {
                       100%;
                      color: #000;
                      background: #96b377;
                      font: 14px Helvetica, Arial, sans-serif;
                  }
      
                  a {
                      text-decoration: none;
                      color: green;
                  }
      
                  #test_box {
                       100px;
                      height: 100px;
                      background-color: red;
                  }
              <style/>
          </head>
          
          <body>
              
              <div id="test_box" class="clearfix"></div>
              
              <!-- javascript 代码 -->
              <script type="text/javascript" src="./js/index.js">
                  window.addEventListener("DOMContentLoaded", function(){
                      var testBox = document.getElementById("test_box");
                      
                      /**** requestAnimationFrame ****/
                      var element = testBox;
                      element.style.position = 'absolute';
                      
                      var start = null;
                      var offset = 0;
                      var speed = 5;
                      function step(timestamp) {
                          if (!start){
                              start = timestamp;
                          };
                          var progress = (timestamp - start)/speed;
                          endPos = 500;
                          
                          // 元素不断向左移,最大不超过200像素
                          offset = progress;
                          if(parseInt(progress/endPos)%2 == 0){
                              offset = progress%endPos;
                          }else{
                              offset = endPos - progress%endPos;
                          };
                          
                          element.style.left = offset%endPos + 'px';
                          
                          // 如果距离第一次执行不超过 2000 毫秒,
                          // 就继续执行动画
                          //if (progress < 2000) {
                              window.requestAnimationFrame(step);
                          //};
                      };
                      
                      window.requestAnimationFrame(step);
                  }, false);
              </script>
          </body>
      </html>
  • 相关阅读:
    软件工程笔记
    人工智能学习笔记
    Linux学习笔记
    【Java】SpringMVC+JSP部署服务器配置
    【Android】是时候为你的应用加上WebDav同步了
    【Android】发布你的第一个开源程序到jcenter遇到的坑
    【C#】支持私聊、多人聊天、图片发的TCP程序
    【Android】让你的安卓app国际化、支持语言自动切换
    【Java】创建一个Maven管理的Web项目并连接数据库
    JS 事件循环怎么处理宏任务和微任务?
  • 原文地址:https://www.cnblogs.com/baixiaoxiao/p/10573526.html
Copyright © 2011-2022 走看看