滚动事件上带有clearAnimationFrame的requestAnimationFrame

时间:2018-12-25 11:11:57

标签: javascript requestanimationframe cancelanimationframe

关于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);

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

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

1 个答案:

答案 0 :(得分:0)

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>

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

因此回到您的主要问题

  

在这种情况下,带有和不带有cancelAnimationFrame的性能是否有区别?

通常不,因为您的requestAnimationFrame()调用阻止了下一个scroll回调,并且您执行的滚动回调不能超过请求的帧回调,因此存在1对1的相关性,因为它们两者都每帧渲染最大发生一次。

  

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

所有请求的动画帧回调都堆积在callbacks的内部池中,在最近的Vsync事件之前将其刷新。因此,从技术上讲,是删除计划的回调的唯一方法是cancelAnimationFrame(),但这又与您的情况无关,因为您的requestAnimationFrame()回调发生在窗口scroll回调的“相同”时间

希望有道理。