15

所以,也许这里完全是脑残。for 的语法setInterval()很清楚。每 x 毫秒做一些事情。这如何最好地翻译成使用requestAnimationFrame()?

我有大约 300 个对象,每个对象都应该以一定的间隔(每 8、6、2 等秒)执行一个动画序列?我怎样才能最好地使用requestAnimationFrame()每秒调用约 60 次的方法来完成此操作?可能有一个简单的答案,我只是,为了我的一生,无法弄清楚。

4

2 回答 2

11

要强制 requestAnimationFrame 坚持特定的 FPS,您可以同时使用两者!

var fps = 15;
function draw() {
    setTimeout(function() {
        requestAnimationFrame(draw);
        // Drawing code goes here
    }, 1000 / fps);
}

有点奇怪,但不是世界上最令人困惑的事情。

您也可以使用 requestAnimationFrame 而不是 FPS,而是使用经过的时间,以便根据自上次调用以来的时间差绘制需要更新的对象:

var time;
function draw() {
    requestAnimationFrame(draw);
    var now = new Date().getTime(),
        dt = now - (time || now);
 
    time = now;
 
    // Drawing code goes here... for example updating an 'x' position:
    this.x += 10 * dt; // Increase 'x' by 10 units per millisecond
}

这两个片段来自这篇精美的文章,其中包含更多详细信息。

顺便问下好问题!我认为我也没有在 SO 上看到这个答案(而且我在这里太多了)

于 2012-08-14T02:20:12.437 回答
10

requestAnimationFrame是相当低的水平,它只是做了你已经说过的:大约以 60fps 的速度被调用(假设浏览器可以跟上那个速度)。因此,通常您需要在此基础上构建一些东西,就像具有游戏循环的游戏引擎一样。

在我的游戏引擎中,我有这个(在此处进行分段/简化):

window.requestAnimationFrame(this._doFrame);

...

_doFrame: function(timestamp) {
     var delta = timestamp - (this._lastTimestamp || timestamp);

     for(var i = 0, len = this.elements.length; i < len; ++i) {
         this.elements[i].update(delta);
     }

     this._lastTimestamp = timestamp;

     // I used underscore.js's 'bindAll' to make _doFrame always
     // get called against my game engine object
     window.requestAnimationFrame(this._doFrame);
 }

然后我的游戏引擎中的每个元素都知道如何更新自己。在您的情况下,应该每 2、6、8 秒更新一次的每个元素都需要跟踪已经过去了多少时间并相应地更新:

update: function(delta) {
     this.elapsed += delta;

     // has 8 seconds passed?
     if(this.elapsed >= 8000) {
          this.elapsed -= 8000;  // reset the elapsed counter
          this.doMyUpdate(); // whatever it should be
     }
 }

Canvas API 以及requestAnimationFrame相当低级的 API,它们是动画和游戏引擎之类的构建块。如果可能的话,我会尝试使用现有的,比如 cocos2d-js 或者这些天里的其他任何东西。

于 2012-08-13T22:25:25.377 回答