Is there a way to cancel requestAnimationFrame without a global variable?

瘦欲@ 提交于 2021-02-04 21:34:46

问题


I'm trying to cancel a requestAnimationFrame loop, but I can't do it because each time requestAnimationFrame is called, a new timer ID is returned, but I only have access to the return value of the first call to requestAnimationFrame.
Specifically, my code is like this, which I don't think is entirely uncommon:

function animate(elem) {

  var step = function (timestamp) {

    //Do some stuff here.
    if (progressedTime < totalTime) {
      return requestAnimationFrame(step); //This return value seems useless.
    }

  };

  return requestAnimationFrame(step);

}

//Elsewhere in the code, not in the global namespace.
var timerId = animate(elem);

//A second or two later, before the animation is over.
cancelAnimationFrame(timerId); //Doesn't work!

Because all subsequent calls to requestAnimationFrame are within the step function, I don't have access to the returned timer ID in the event that I want to call cancelAnimationFrame.

Looking at the way Mozilla (and apparently others do it), it looks like they declare a global variable in their code (myReq in the Mozilla code), and then assign the return value of each call to requestAnimationFrame to that variable so that it can be used any time for cancelAnimationFrame.

Is there any way to do this without declaring a global variable?
Thank you.


回答1:


It doesn't need to be a global variable; it just needs to have scope such that both animate and cancel can access it. I.e. you can encapsulate it. For example, something like this:

var Animation = function(elem) {
  var timerID;
  var step = function() {
    // ...
    timerID = requestAnimationFrame(step);
  };
  return {
    start: function() {
      timerID = requestAnimationFrame(step);
    }
    cancel: function() {
      cancelAnimationFrame(timerID);
    }
  };
})();

var animation = new Animation(elem);
animation.start();
animation.cancel();
timerID; // error, not global.

EDIT: You don't need to code it every time - that's why we are doing programming, after all, to abstract stuff that repeats so we don't need to do it ourselves. :)

var Animation = function(step) {
  var timerID;
  var innerStep = function(timestamp) {
    step(timestamp);
    timerID = requestAnimationFrame(innerStep);
  };
  return {
    start: function() {
      timerID = requestAnimationFrame(innerStep);
    }
    cancel: function() {
      cancelAnimationFrame(timerID);
    }
  };
})();
var animation1 = new Animation(function(timestamp) {
  // do something with elem1
});
var animation2 = new Animation(function(timestamp) {
  // do something with elem2
});


来源:https://stackoverflow.com/questions/31282318/is-there-a-way-to-cancel-requestanimationframe-without-a-global-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!