【问题标题】:requestAnimationFrame with clearAnimationFrame on scroll event滚动事件上带有 clearAnimationFrame 的 requestAnimationFrame
【发布时间】:2018-12-25 11:11:57
【问题描述】:

关于 JavaScript 的 requestAnimationFrame 已经有很多问题了,(我认为)我理解这个概念,但是在这种情况下使用和不使用 cancelAnimationFrame 之间是否存在性能差异?

// Setup a timer
var timeout;

// Listen for resize events
window.addEventListener('scroll', function () {

    console.log( 'no debounce' );

    // Cancel last animation, if there's one
    if (timeout) {
        window.cancelAnimationFrame(timeout);
    }

    // Setup the new requestAnimationFrame()
    timeout = window.requestAnimationFrame(function () {

        // Run our scroll functions
        console.log( 'debounced' );

    });

}, false);

没有cancelAnimationFrame

// Setup a timer
var timeout;

// Listen for resize events
window.addEventListener('scroll', function () {

    console.log( 'no debounce' );


    // Setup the new requestAnimationFrame()
    window.requestAnimationFrame(function () {

        // Run our scroll functions
        console.log( 'debounced' );

    });

}, false);

我在每个代码上得到相同的结果。

但我想知道如果我不取消动画帧会发生什么。请求的函数是否堆积在内存中的某个地方或其他地方?

【问题讨论】:

    标签: javascript requestanimationframe cancelanimationframe


    【解决方案1】:

    var isRafLogged = false;
    
    function rafCb(now) {
      if (isRafLogged) {
        console.log('rAF callback executed at: ', now, 'ms');
      }
      requestAnimationFrame(rafCb);
    }
    
    function onWindowScroll() {
      // when in scroll, log aforescheduled rAF() only when in scroll
      isRafLogged = true;
      const now = performance.now();
    
      console.log('scroll callback executed at: ', now, 'ms');
    
      // when out of scroll, stop logging the rAF
      setTimeout(function() {
        isRafLogged = false;
      });
    }
    
    requestAnimationFrame(rafCb);
    
    window.addEventListener('scroll', onWindowScroll);
    html,
    body {
      height: 10000px;
    }
    
    p {
      font-size: 200px;
      writing-mode: vertical-lr;
    }
    <p>.....................................................................................................................................................................................................................................................................................................................................................................</p>

    如果我们在scroll 时安排一个连续的单独的requestAnimationFrame 循环,我们将清楚地看到rAFscroll 回调正在发生 每个VSync event 最多一次。

    回到你的主要问题

    在这种情况下,使用和不使用 cancelAnimationFrame 有什么性能差异吗?

    通常不会,因为您的 requestAnimationFrame() 调用阻塞了下一个 scroll 回调,并且您执行的滚动回调不能多于您请求的帧回调,因此存在 1 对 1 的相关性,因为它们都在每帧渲染。

    但我想知道如果我不取消动画帧会发生什么。请求的函数是否堆积在内存中的某个地方或其他地方?

    所有请求的动画帧回调都堆叠在callbacks 的内部池中,在最近的垂直同步事件之前被刷新。所以是的,从技术上讲,删除预定回调的唯一方法是 cancelAnimationFrame(),但同样与您的情况无关,因为您的 requestAnimationFrame() 回调与窗口 scroll 回调“同时”发生。

    希望它有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-03
      • 2014-07-01
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 2015-01-29
      • 1970-01-01
      • 2016-12-09
      相关资源
      最近更新 更多