On my application, I have a canvas which CSS size (CSS, not html) updates depending on the window size.

I have a main gameplayLoop which looks like this :

run = function(){

    console.log(timerDiff(frameTime));

    game.inputManage();
    game.logics();
    game.graphics.animate();
    game.graphics.render();

    frameTime = timerInit();

    requestAnimFrame(run);

}

My requestAnimFrame function is the one from Paul Irish :

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

So basically the problem is that the timer that I log which measures the time between the requestAnimFrame call and the effective function call totally changes. If my browser is in fullscreen I get like 50/60 ms, and if I have a small window I can get to something like 10 ms.

As the requestAnimFrame call is supposed to call constantly the function under a 60fps rythm (which is something like 30 ms I think) I shouldn't have this kind of result, since there is basically nothing happening between the timer's creation and its check, except the requestAnimFrame

I also have some recurring micro-freezes (less than a second) which happens like every 2/3 seconds. But the timer doesn't detect any change in the time (like even the time counter of javascript is blocked)

My timers functions are like this but it doesn't really matter here

timerInit = function()
{
    return new Date();
}

timerDiff = function(datePrev)
{
    return new Date().getTime() - datePrev.getTime();
}
有帮助吗?

解决方案

Well, the standard basically says that requestAnimationFrame will "do its best" to run at a "consistent" frame rate. That doesn't guarantee a 60fps; it just states that it will animate as fast as it can.

My experience with it has been as dim as yours so far unfortunately. I ended up going back to setTimeout. It goes at about the same rate, and graphical updates are accurate and don't skip a beat as they did with requestAnimationFrame. Sure it wasn't 60fps, but at least you could tell what was going on.

I'm sure the performance will only improve as browser developers optimize the new function, but for the time being, consider going back to timeouts.

Edit: I would like to remind people that this was answered a year ago, and the times have changed :)

其他提示

"So basically the problem is that the timer that I log which measures the time between the requestAnimFrame call and the effective function call totally changes..."

Of course it does, that's why you need to measure it and BASED ON THIS TIME DIFFERENCE VALUE you calculate your next frame.

Let's assume you want to animate the 'left' css property of a div from 0px to 120px in 1 second with 60 fps.

  • using setTimeout, because YOU set the number of frames, you know how much you must increment the 'left' property: 120px/60frames = 2px/frame

  • using requestAnimationFrame, you have no ideea when the next frame will happen, until it happens; then you measure the time difference between this and the previous frame an you calculate the value you must increment the css 'left value' with; if the frame happens after 500ms, increment distance = (120px * 500ms)/1000ms = 60px; the ideea is that at the start of the animation you can't have a fixed, predetermined value to increment with at each frame, you need to calculate it dynamically based on the time difference

So even if the animation won't be at the advertised 60fps, if frames are skipped, every frame that is not skipped will draw the accurate updated situation.

You have to fiddle a bit to decide when the animation should end.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top