【问题标题】:Run JavaScript code every second with rAF.js?使用 rAF.js 每秒运行 JavaScript 代码?
【发布时间】:2013-05-20 17:16:07
【问题描述】:

根据以下帖子,我从使用 setTimeout 转移到 requestAnimationFramehttp://paulirish.com/2011/requestanimationframe-for-smart-animating/

如何在我的animation() 循环中设置一些代码以每秒执行一次?

我目前正在做类似的事情:

animate() {
  if(playGame) {
    requestAnimFrame(animate);
  }

  var time = new Date().getTime();

  if(time % 1000 <= 10) {
    // code to run ~every second
  }

  // Also need to fix this, as it executes too fast, need to add score only 
  // every 100 milliseconds (player must stay in zone for 2 seconds to win)
  if(playerInZone()) {
    gameScore++;
    if(gameScore >= 100) {
      endGame();
    }
  } else {
    gameScore = 0;
  }

}

我不确定这样调用时间并执行模数是否正确?我还可以通过什么方式将我的 gameScore 代码更改为仅每(例如)200 毫秒触发一次?

注意:
我在我的 JavaScript 文件顶部使用此代码:

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          window.oRequestAnimationFrame      ||
          window.msRequestAnimationFrame     ||
          function(/* function */ callback, /* DOMElement */ element){
            window.setTimeout(callback, 1000 / 60);
          };
})();

但我也将 rAF.js 包含在我的文件中,但不确定使用哪个:

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel

// MIT license

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

【问题讨论】:

  • 你可以使用 setInterval 或 setTimeout
  • 我注意到您使用了 Paul 的“requestAnimFrame”(这是他在规范仍在不断变化时提出的)。相反,我会建议在同一页面的标题“强大的 polyfill”下使用他真正的 polyfill
  • 我可能会将时间敏感的游戏逻辑与渲染逻辑分开。
  • @Strille - 我已经用 rAF 代码更新了我的问题。
  • @DanSaltmer - 我该怎么做?活动?

标签: javascript


【解决方案1】:

当 requestAnimationFrame 被调用时,“当前时间”以毫秒为单位发送,所以你可以这样做:

var lastTime = 0;

animate(currentTime) {
  if (currentTime >= lastTime + 1000)  {
     // one second has passed, run some code here

     lastTime = currentTime;
  }


  if(playGame) {
    requestAnimationFrame(animate);
  }
}

【讨论】:

  • 对不起,您需要在 animate 中再次调用 requestAnimationFrame,我已经编辑了我的示例。
  • 为什么我需要多次?我应该在脚本底部使用它吗?
  • 调用requestAnimationFrame并发送一个函数基本上意味着:“你好浏览器。下一次你更新屏幕时,请运行这段代码。”。请注意,它是“下一次”而不是“每次”。所以,一旦代码运行,如果你想让它“循环”,你需要调用requestAnimationFrame
  • 只调用requestAnimtionFrame 似乎只有在我切换到另一个选项卡然后切换回“游戏”时才会运行。两次调用requestAnimationFrame 似乎导致选项卡超载和崩溃?
  • 是的,requestAnimtionFrame 仅在浏览器选项卡可见时运行。这就是重点。对于大多数游戏来说,这完全没问题。但是,如果您总是需要运行循环,则需要使用 setInterval 或 setTimeout。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 2015-04-28
  • 1970-01-01
  • 2011-03-24
  • 2015-03-27
  • 2020-08-10
相关资源
最近更新 更多