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 webxl

HTML

Using <span id="func"></span> for window.requestAnimFrame. <br>

setTimeout <span id="time_st"></span>ms<br>
<canvas id="st" width="300" height="20" class="bar"></canvas>
<br>
requestAnimationFrame <span id="time_af"></span>ms<br>
<canvas id="af" width="300" height="20" class="bar"></canvas>

CSS

.bar {
    border: 3px solid #000000;
}

JavaScript

/* forked from http://jsfiddle.net/calpo/H7EEE/ */

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          window.oRequestAnimationFrame      ||
          window.msRequestAnimationFrame     ||
          function requestAnimationFrameSHIM(/* function */ callback, /* DOMElement */ element){
            window.setTimeout(callback, 1000 / 60);
          };
})();

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

var st = {
    ctx: $('#st')[0].getContext("2d"),
    len: 0,
    $disp: $('#time_st')
};
var af = {
    ctx: $('#af')[0].getContext("2d"),
    len: 0,
    $disp: $('#time_af')
};

st.ctx.fillStyle = 'red';
af.ctx.fillStyle = 'blue';

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

$('#func').html(window.requestAnimFrame.name);

function render(obj){
    heavy_process();
    obj.ctx.fillRect(obj.len,0,1,20);
    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, 1000 / 60);
}());
(function af_loop(){
    if( !render(af) ){
        return false;
    }
    requestAnimFrame(af_loop);
}());