将setInterval与requestAnimationFrame一起使用

时间:2014-09-16 22:32:30

标签: javascript google-chrome requestanimationframe

我想在程序中使用setInterval来实现步骤,并使用requestAnimationFrame进行渲染。我认为这将是完美的混合:渲染速度不会减慢实际进度,因此帧速率的下降只会影响帧速率并仍然同步。然而,我得到的是setInterval函数的下降。

我的意思的一个例子,故意陷入阴影:http://jsfiddle.net/Ltdz168m/

减少或增加补充次数,你会看到差异

看来requestAnimationFrame实际上是一种解决方案,可以减缓JavaScript的速度。那么我如何更新事物的逻辑方面,可以在60 fps下完成,而不会妨碍渲染? WebWorkers绝对必要吗?

1 个答案:

答案 0 :(得分:17)

问题是浏览器仍然只能一次做一件事。因此,如果它正在渲染,则无法更新位置。

在做支持可变帧速率的东西时,你应该总是使用Delta Timing。它的工作原理如下:

requestAnimationFrame(function(e) {
  document.getElementById('status').innerHTML = "Delta time: "+e;
  
  // lag randomly
  while(Math.random() > 0.0000001) {}
  
  requestAnimationFrame(arguments.callee);
});
<div id="status"></div>

正如您所见(希望如此),无论帧速率如何,显示的增量时间都会持续增加。这意味着您可以执行angleFromStart = e/1000*Math.PI*2;,并且您的点将以精确的60 RPM运行。

var angle=0,
    radian=Math.PI/180;
var canvas=document.getElementById("canvas"),
    context=canvas.getContext("2d");
context.shadowColor="black";
context.shadowBlur=100;
requestAnimationFrame(function draw(e) {
  angle = e/1000*Math.PI*2;
    var x=canvas.width/2+Math.cos(angle)*canvas.width/4,
        y=canvas.height/2+Math.sin(angle)*canvas.height/4;
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
    context.arc(x, y, 5, 0, Math.PI*2);
    context.closePath();
    for(var i=0; i<255; i++) {
        context.fill();
    }
    requestAnimationFrame(draw);
});
#canvas {
    border: 1px solid black;
}
<canvas id="canvas"></canvas>

PS:我喜欢新的Stack Snippet功能!