requestAnimationFrame vs setTimeout

animation(or game) loop with requestAnimationFrame progress bar with setTimeout will be delayed by heavy process. one with requestAnimationFrame will be drawn on accurate time course on GoogleChrome. (not good on firefox)

by calpo

HTML

setTimeout <span id="time_st"></span>ms<br>
<div class="box"><div id="st" class="bar"></div></div>
<br>
requestAnimationFrame <span id="time_af"></span>ms<br>
<div class="box"><div id="af" class="bar"></div></div>

CSS

.box {
    width: 300px;
    height: 20px;
    text-align: left;
    border: 3px solid #000000;
}

.bar {
    width: 0px;
    height: 100%;
    background-color: #999999;
}

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);
          };
})();

function heavy_process(){
    var stoptime = Math.floor(Math.random() * 12); 
    var start = (new Date()).getTime();
    while((new Date()).getTime() - start < stoptime){
        // sleep
    }
}

var $st = $('#st'),
    $af = $('#af');
var len_st = 0,
    len_af = 0;
var time_st = (new Date()).getTime(),
    time_af = (new Date()).getTime();

function render_st(){
    heavy_process();
    $st.css('width', len_st +'px');
    len_st += 1;
}
function render_af(){
    heavy_process();
    $af.css('width', len_af +'px');
    len_af += 1;
}

function st_loop(){
    render_st();
    if(len_st > 300){
        $('#time_st').text((new Date()).getTime() - time_st);
        return true;
    }
    setTimeout(st_loop, 16.667);
}
function af_loop(){
    render_af();
    if(len_af > 300){
        $('#time_af').text((new Date()).getTime() - time_af);
        return true;
    }
    requestAnimFrame(af_loop);
}
st_loop();
af_loop();