本节主要是动画循环相关的知识

       在准备好HTML5文件的基本模板之后,已经可以编码了,只要再有一个支持HTML5的web浏览器,就完事具备

动画循环

       几乎所有程序动画都会表现为某种形式的循环

graph LR A(显示
第1帧)-->B(显示
第2帧) B-->C(显示
第3帧) C-->D(......)

逐帧动画

       代码会读取这些相关数据,并根据这些数据将对象绘制出来,从而显示这些帧

graph LR A(渲染
第1帧)-->B(渲染
第2帧) B-->C(渲染
第3帧) C-->D(......)

渲染并显示每一帧

       而描述一个动态的,编码的动画流程图则如下图所示

graph LR A(获取初
始状态)-->B(渲染帧) B-->C(应用
规则) C-->D(结束了?) D-->|是|E(显示帧) D-->|否|B

脚本动画

       同一套规则(e.g:球向右移动5像素)会不断重复利用,构成循环,就能形成动画。但是,下面的解释是许多初学者的一种误解:循环的运行依赖于几乎所有编程语言中的while循环结构

while(true) {
    ball.x += 1;
}

       为了实现动画,要为每一帧执行以下操作:

  1. 执行该帧锁钥调用到的代码
  2. 将所有对象绘制到canvas上
  3. 重复该过程渲染下一帧

       所以,代码实质应该是一个类似下面的代码

function drawFrame() {
    ball.x += 1;
    ball.draw(context);
}

window.setInterval(drawFrame, 1000/60);

       本例中,以1000/60的时间间隔来调用 drawFrame 函数,即60FPS,每隔大约 17ms 执行一次绘制函数。

使用requestAnimationFrame的动画循环

       由于开发者对基于HTML5的动画兴趣日益增长,Web浏览器专门为JavaScript的开发者实现了一个API,用过它提供了基于浏览器的优化实现。 window.requestAnimationFrame 接受一个回调函数作为参数,并确保在重绘屏幕之前执行该回调函数。可以通过对 requestAnimationFrame 函数的链式调用实现动画循环:

(function drawFrame(){
    window.requestAnimationFrame(drawFrame, canvas);

    // animation code
}());

       上面的代码,定义了drawFrame函数,包含了每帧要执行的动画代码,第一行调用了window.requestAnimationFrame 函数,将drawFrame函数自身的引用作为参数传入。第二个可选参数是要绘制的canvas。

       当执行drawFrame函数时,window.requestAnimationFrame 将drawFrame函数放入队列等待下一个动画间隔中再次执行,而它再次执行时又会重复着一过程。由于不断的请求执行该函数,因此串联成了一个循环。

       由于 requestAnimationFrame 是一个相对新的功能,因此目前的浏览器还致力于各自的实现。如果希望代码具备更好的跨平台性,下面一段代码可以用来规范该函数在不同浏览器中的实现。

if (!window.requestAnimationFrame) {
  window.requestAnimationFrame = (window.webkitRequestAnimationFrame ||
                                  window.mozRequestAnimationFrame ||
                                  window.msRequestAnimationFrame ||
                                  window.oRequestAnimationFrame ||
                                  function (callback) {
                                    return window.setTimeout(callback, 17 /*~ 1000/60*/);
                                  });