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

var start_time = (new Date()).getTime();

var st = {
    $elm: $('#st'),
    len: 0,
    $disp: $('#time_st')
};
var af = {
    $elm: $('#af'),
    len: 0,
    $disp: $('#time_af')
};

function heavy_process(){
    var stoptime = 8; 
    var start = (new Date()).getTime();
    while((new Date()).getTime() - start < stoptime){
        // sleep
    }
}

function render(obj){
    heavy_process();
    obj.$elm.css('width', obj.len +'px');
    obj.len += 1;
    if(obj.len > 300){
        obj.$disp.text((new Date()).getTime() - start_time);
        return false;
    }
    return true;
}

(function st_loop(){
    if( !render(st) ){
        return false;
    }
    setTimeout(st_loop, 16.667);
}());
(function af_loop(){
    if( !render(af) ){
        return false;
    }
    requestAnimFrame(af_loop);
}());