如何在requestAnimationFrame中传递参数?

31
在主程序中,我随机选择一个要进行动画的对象,并将该对象作为参数调用函数。第一个循环正常,x被正确设置,但在下一轮中它变成了undefined
类似这样的情况:
var anim = {
        mainFunc: function(x) {
            anim.update(x);
            anim.redraw(x);
            window.requestAnimationFrame(anim.mainFunc);
        },

        update: function(x) {

        },

        redraw: function(x) {

        }
};

var n=Math.floor(Math.random() * (ArrayOfAnimObject.length));
anim.mainFunc(ArrayOfAnimObject[n]);
4个回答

46

您需要创建一个引用,或者像这样将函数调用包装在另一个函数中:

您可以创建一个引用来存储函数,然后通过该引用进行调用,或者使用匿名函数将函数调用包装起来。例如:

mainFunc: function(x) {
    anim.update(x);
    anim.redraw(x);
    window.requestAnimationFrame(function() {
        anim.mainFunc(x);
    });
}

太好了! :) 谢谢! - Torfiks
为什么 x 没有像这样明确地传递:window.requestAnimationFrame(function(x) { anim.mainFunc(x); - Thomas An
1
因为在你的示例中回调函数中的 x 不是传递给周围函数的参数。requestAnimationFrame 只向它所调用的函数传递一个时间戳。 - kalley

25

您还可以使用.bind

mainFunc: function(x) {
    anim.update(x);
    anim.redraw(x);
    window.requestAnimationFrame(anim.mainFunc.bind(anim,x));
}

8
最好的方法可能是避免这样做。
要实现这一点,需要创建一个新的函数(可以是@kalley答案中的匿名包装器或@ArchyWillHe的绑定函数)每一帧都要创建
在动画循环中,您希望尽可能少地留下不可回收的对象,以便垃圾回收器不必在您的动画运行时启动,从而在发生时杀死几个帧。
为了实现这一点,您有不同的策略可用,但例如在OP中公开的情况下,这个x参数可能应该直接附加到anim对象上:

var anim = {
  mainFunc: function() {
    anim.update();
    anim.redraw();
    window.requestAnimationFrame(this.mainFunc);
  },

  update: function() {
    this.x ++;
  },

  redraw: function() {
    log.textContent = this.x;
  }
};
// replace it with a bound function only once
anim.mainFunc = anim.mainFunc.bind(anim);
anim.x = 0; // attach the parameter to the anim object
anim.mainFunc();
<pre id="log"></pre>

有些人可能会更喜欢将此参数仅作为一个变量供调用者和anim使用:

(function() {

var anim = {
  mainFunc: function() {
    anim.update();
    anim.redraw();
    window.requestAnimationFrame(anim.mainFunc);
  },

  update: function() {
    x ++;
  },

  redraw: function() {
    log.textContent = x;
  }
};
var x = 0; // available for both us and anim's method
anim.mainFunc();

})();
<pre id="log"></pre>


0
10年前! 这是我做的方法:将第二个函数附加到动画函数中:
  let nloop=0, nfunc=0;
  animate.func = func1; // attach func1 to animate
  animate();
function animate() {
  if (animate.func) animate.func(); // call the attached function
  // or just "animate.func();" if something is always attached
  document.body.innerHTML = ++nloop +', ' + nfunc;
  requestAnimationFrame(animate);
}
function func1() { // the attached function
  nfunc += 1; 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接