requestAnimationFrame中的时间控制

9
在我正在建设的城市交通模型中,我试图获得正确的时序。 我想能够: a)设置动画速度——我推测现在它正尝试着以60帧每秒的速度运行,但我想能够将其设置为更快或更慢的速度。 我尝试了这段代码:
var fps = 5;
function draw() {
    setTimeout(function() {
       requestAnimationFrame(animate);
  }, 1000 / fps);
}
draw();

但是由于rAF被调用了三次,我不确定如何实现它。我尝试在所有三个上使用它,但没有成功。

b) 我想为每个“车辆”的启动设置一个轻微的延迟,以便它们不会同时出发。

这里是代码演示:https://jsfiddle.net/g3yhr00L/


在你的fiddle中,你想做什么不是很清楚。例如,第88行什么也没做- time < lastTime总是会是false,因为你设置了lastTime = 0并且从未更改它。你只是想控制动画速率吗? - caasjj
2个回答

9
为了减缓动画,只需要这样做:
// define some FRAME_PERIOD in units of ms - may be floating point
// if you want uSecond resolution
function animate(time) {
    // return if the desired time hasn't elapsed
    if ( (time - lastTime) < FRAME_PERIOD) {
        requestAnimationFrame(animate);
        return;
    }

    lastTime = time;

    // animation code

}

要更改车辆的启动时间,您需要在车辆本身的逻辑中构建它。我不会单独为每个车辆制作动画。

你应该从animate函数中移除时间参数,因为你已经在全局使用了lastTime和time,它们的定义超出了函数作用域。 - Saar
@saar 不,time并不在全局范围内定义。它是通过requestAnimationFrame传递给animate的。当requestAnimationFrame调用animate时,它会将一个非常精细的时间度量传递给它——如下面我的评论中所述的链接描述。 - caasjj
lastTime 必须在闭包中声明,不一定是全局的,但是不能在 animate 的作用域中声明。lastTimetime 是两个非常不同的东西。 - caasjj
是的,当我说全局时,我指的是函数之外,当然你可以将它包装在闭包中。我不知道时间已经过去了,谢谢。 - Saar
简单有用,是的! - benzkji

8

这是我在寻找限制FPS时发现的一种方法。

它非常好,附有说明:编辑:不需要使用Date.now()。

var fps = 30;
var now;
var then;
var interval = 1000/fps;
var delta;

function draw(now) {
    if (!then) { then = now; }
    requestAnimationFrame(draw);
    delta = now - then;

    if (delta > interval) {
        // update time stuffs

        // Just `then = now` is not enough.
        // Lets say we set fps at 10 which means
        // each frame must take 100ms
        // Now frame executes in 16ms (60fps) so
        // the loop iterates 7 times (16*7 = 112ms) until
        // delta > interval === true
        // Eventually this lowers down the FPS as
        // 112*10 = 1120ms (NOT 1000ms).
        // So we have to get rid of that extra 12ms
        // by subtracting delta (112) % interval (100).
        // Hope that makes sense.

        then = now - (delta % interval);

        // ... Code for Drawing the Frame ...
    }
}

draw();

您可以在此处找到原始文章: http://codetheory.in/controlling-the-frame-rate-with-requestanimationframe/

本文介绍了如何使用requestAnimationFrame控制动画的帧速率。通过使用该方法,可以避免出现卡顿和过度渲染的问题,并且能够更好地利用浏览器的资源。


4
不需要使用Date.nowrequestAnimationFrame会将一个时间戳传递给draw函数。事实上,你不应该使用Date.now,可以参考https://developer.mozilla.org/en-US/docs/Web/API/Performance/now。 - caasjj
这样做不会跳过第一帧吗?因为在第一次调用时,delta === 0,它不大于间隔。所以你会在第一秒钟得到59帧。 - Aleksandr Hovhannisyan

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