为什么requestAnimFrame被调用2次?

时间:2014-11-01 03:41:57

标签: javascript html5 html5-canvas requestanimationframe

我正在跟随this书来了解html5画布动画,我想知道,在这段代码中:

// shim layer with setTimeout fallback 
window.requestAnimFrame = (function(){ 
  return  window.requestAnimationFrame       ||  
          window.webkitRequestAnimationFrame ||  
          window.mozRequestAnimationFrame    ||  
          window.oRequestAnimationFrame      ||  
          window.msRequestAnimationFrame     ||  
          function( callback ){ 
            window.setTimeout(callback, 1000 / 60); 
          }; 
})();

var x = 0; 
function drawIt() { 
    window.requestAnimFrame(drawIt); 
    var canvas = document.getElementById('canvas'); 
    var c = canvas.getContext('2d'); 
    c.fillStyle = "red"; 
    c.fillRect(x,100,200,100); 
    x+=5; 
} 
window.requestAnimFrame(drawIt);

为什么要在drawIt函数的外部和内部调用window.requestAnimFrame(drawIt)

1 个答案:

答案 0 :(得分:0)

详细说明大多数已在评论中说明的内容(附加一些提示) -

requestAnimationFrame对作为参数传入的函数进行单个异步调用。这意味着需要连续调用该方法来创建动画循环。

调用更新下一帧的调用的逻辑位置来自循环本身。但是,循环只是一个函数,也需要调用,因此需要初始调用以启动"循环。 (因此,考虑一种破坏循环的机制也是明智的。)

另一种技术可能是使用自我调用的调用。在这种情况下,代码看起来就像这样,没有初始调用:

(function drawIt() { 
    window.requestAnimFrame(drawIt); 
    var canvas = document.getElementById('canvas'); 
    var c = canvas.getContext('2d'); 
    c.fillStyle = "red"; 
    c.fillRect(x,100,200,100); 
    x+=5; 
})();

评估第一对括号内的函数,而第二对将调用任何被评估的函数,即。功能。如果你选择了这个,或者原件或多或少是个人品味的问题(第一帧不会更新,直到第一个下一个可用的显示器刷新,所以你不会在第一次做手动更新时有任何故障)。

另一件值得注意的事情是:获取对canvas和context的引用通常永远不会在 inside 循环中完成,因为它们是相对昂贵的操作。尝试始终获取循环外的那些,只有一次:

var canvas = document.getElementById('canvas'); 
var c = canvas.getContext('2d'); 

(function drawIt() { 
    window.requestAnimFrame(drawIt); 
    c.fillStyle = "red";       // also a potential candidate for optimizing
    c.fillRect(x,100,200,100); 
    x+=5; 
})();

如果您只设置一次颜色,也可以将其移动到循环外(即。fillStylestrokeStyle等)。这些在动画方面也很昂贵。