如果我尝试多次运行JSfiddle中发布的代码,则会得到不同数量的div(我假设animeframe在1秒钟内未完全完成)

http://jsfiddle.net/ghjKC/133/

    // shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
    return  window.requestAnimationFrame       ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame    ||
        window.oRequestAnimationFrame      ||
        window.msRequestAnimationFrame     ||
        function(/* function */ callback, /* DOMElement */ element){
            return window.setTimeout(callback, 1000 / 60);
        };
})();
window.cancelRequestAnimFrame = ( function() {
    return window.cancelAnimationFrame            ||
        window.webkitCancelRequestAnimationFrame    ||
        window.mozCancelRequestAnimationFrame         ||
        window.oCancelRequestAnimationFrame        ||
        window.msCancelRequestAnimationFrame        ||
        clearTimeout
} )();

var request;

(function animloop(){
    console.log("render() should be done here and now");
    request = requestAnimFrame(animloop, $("#time").append("<div></div>"));
})();

// cancelRequestAnimFrame to stop the loop in 1sec
console.log("will do cancelRequestAnimFrame in 1sec...")
setTimeout(function(){
    console.log("1sec expired doing cancelRequestAnimFrame() now")
    cancelRequestAnimFrame(request);
}, 1*1000)


我的问题是如何确保获得相同数量的div?

最佳答案

关于setTimeoutrequestAnimationFrame回调的精度不能保证。

setTimeout非常不准确。

requestAnimationFrame取决于您的系统呈现页面的速度。如果页面非常复杂且帧速率下降,则每秒将调用回调少于60次。

现在,如果您解释您的实际问题是什么,我们可以尝试找到一个好的解决方案。

您说过要恒定数量的<div>,这意味着恒定数量的执行。这不能通过时间来控制。根据您的用例,您可以直接控制执行次数。例如。运行您的回调60次(理想情况下,使用requestAnimationFrame将其接近1s)。

编辑
根据您的评论:如果您要制作进度条,该进度条会在1秒内顺利填充。最好的方法是:使用requestAnimationFrame,传递给回调的第一个参数是高精度时间。通过此计算,您应该填充进度条的数量。如果时间> 1秒,请不要再请求其他帧。

大意:

var startTime;

function startProgress() {
  startTime = null;
  requestAnimationFrame(progress);
}

function progress(time) {
  if (startTime === null) startTime = time;
  // Compute progress since last frame
  var ratio = (time - startTime) / 1000; // time is in [ms]
  // Here you should update your progress, maybe this:
  // Note I've used Math.min because we might go over 100% due to callback time.
  $(".progressDiv").width(Math.min(ratio, 1) * 300);
  // If we're not done yet, request a new animation frame
  if (ratio < 1) requestAnimationFrame(progress);
}

10-04 16:42