7

所以我一直是一个优秀的网民,使用功能检测来查看浏览器是否支持requestAnimationFrame,否则只能退回到setTimeout基于 - 的解决方案(类似于Paul Irish 的著名帖子)。

var NOW = Date.now || function () { return new Date.getTime(); };
var reqAnimFrame =
        window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        /*                        ... ||                     */
        function (callback) {
            setTimeout(function () { callback(NOW()); }, 1000 / 60);
        };

var previousTime = NOW();
function animStep(time) {
    var timePassed = time - previousTime;
    myCharacter.move(myCharacter.speed * timePassed);
    previousTime = time;
    reqAnimationFrame(animStep);
} 

// start the animation
reqAnimationFrame(animStep); 

在 Internet Explorer 10 出现之前,这在任何地方都非常有效。在 IE10 中,time传递的参数似乎与当前时间没有任何关系,搞砸了timePassed.

这是怎么回事?

4

1 回答 1

10

所有(据我所知)实现的其他浏览器requestAnimationFrame都遵循(在撰写本文时)当前工作草案中的规范:

时间为[重绘时间],表示为自 1970-01-01T00:00:00Z 以来的毫秒数。

这和你的一样代表时间NOW()

然而, IE10符合当前编辑草稿中的规范:

time成为在此上下文中调用Performance 接口的 now 方法的结果。

这本质上意味着自浏览器加载此页面以来的毫秒数(这也意味着测量更精确,因为performance.now返回小数毫秒)。

因此,当您timePassed第一次在 IE10 中计算时,您得到的结果类似于负 43 年。

幸运的是,由于传递给requestAnimationFrame回调的值在任何一种情况下都具有相同的单位,只是参考点不同,因此您可以轻松适应这一点。

有三种可能:

  1. 您可以丢弃第一个动画步骤,将其用于 set previousTime,但不做任何其他事情。
  2. 您可以忽略传递的参数并每次都使用您的NOW()(or performance.now),因此始终具有相同的参考点。
  3. 或者您可以将动画的开始更改为:

    // start the animation
    reqAnimationFrame(function (t) {
        previousTime = t - (NOW() - previousTime);
        animStep(t);
    );
    

    timePassed无论浏览器遵循哪个规范,这都会使计算(包括第一个)正确。而且由于它仅更改第一次调用,因此从长远来看,您也没有任何额外的开销。

于 2012-12-18T15:25:25.637 回答