美文网首页
requestAnimationFrame

requestAnimationFrame

作者: my木子 | 来源:发表于2021-05-15 10:52 被阅读0次

用 JS 实现一个循环的动画

  • 导致浏览器卡顿的原因一般都是操作 DOM 的次数太频繁。如果想要渲染很多条数据不造成卡顿,那么就一定要尽可能的减少操作 DOM 的次数。比方说 React 的虚拟 DOM,本质上就是用 JS 数据来模拟真实 DOM树,从而大大减少了操作真是 DOM 的次数。
// html
 <div id="box"></div>
// css
    #box {
      width: 100px;
      height: 100px;
      background: red;
      position: absolute;
      left: 0;
      top: 0;
      zoom: 1;
    }

定时器实现

  • 因为大多数屏幕渲染的时间间隔是每秒60帧,所以时间间隔是1000/60
    let box = document.getElementById("box");
    let flag = true;
    let left = 0;
    let t = null;

    function render() {
      if (flag == true) {
        if (left >= 100) {
          flag = false;
        }
        box.style.left = ` ${left++}px`;
      } else {
        if (left <= 0) {
          flag = true;
          clearInterval(t);
        }
        box.style.left = ` ${left--}px`;
      }
    };

    t = setInterval(function () {
      render()
    }, 1000 / 60);

requestAnimationFrame

  • requestAnimationFrame 是由浏览器专门为动画提供的 API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了 CPU 开销。
    let box = document.getElementById("box");
    let flag = true;
    let left = 0;
    let t = null;

    function render() {
      if (flag == true) {
        if (left >= 100) {
          flag = false
        }
        box.style.left = ` ${left++}px`
      } else {
        if (left <= 0) {
          flag = true
        }
        box.style.left = ` ${left--}px`
      }
    };

    function animationLoop(time) {
      render();
      raf = requestAnimationFrame(animationLoop);
      if (left < 0) {
        cancelAnimationFrame(raf);
      }
    };
    animationLoop();

渲染十万条数据

  • 虚拟 DOM
  • 分段渲染,先使用 document.createDocumentFragment() 创建文档碎片节点,再使用 requestAnimationFrame 逐帧渲染
    let ul = document.querySelector('ul');
    const total = 1000;
    let raf;

    // 分段渲染
    const once = 20;  // 一次渲染的条数
    const loopCount = total / once; // 全部渲染完需要的次数
    let countHasRender = 0;  //  已经渲染的次数
    let num = 0;  // 渲染条数

    function add() {
      // 创建虚拟节点,使用 createDocumentFragment 不会触发渲染
      const fragment = document.createDocumentFragment();
      for (let i = 0; i < once; i++) {
        const li = document.createElement('li');
        li.innerText = num++;
        fragment.appendChild(li);
      };
      ul.appendChild(fragment);
      countHasRender++;
      loop();
    };

    function loop() {
      if (countHasRender < loopCount) {
        raf = requestAnimationFrame(add);
      } else {
        cancelAnimationFrame(raf);
      }
    };

    add();

相关文章

网友评论

      本文标题:requestAnimationFrame

      本文链接:https://www.haomeiwen.com/subject/jfshjltx.html