requestAnimationFrame在IE10中传递意外参数

bal*_*pha 7 javascript internet-explorer-10 requestanimationframe

因此,我一直是一个优秀的网民,使用功能检测来查看浏览器是否支持requestAnimationFrame,setTimeout否则只回归基于解决方案(保罗爱尔兰着名帖子的内容).

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); 
Run Code Online (Sandbox Code Playgroud)

在Internet Explorer 10出现之前,这种方法无处不在.在IE10中,time传递的参数似乎与当前时间无关,搞砸了计算timePassed.

这是怎么回事?

bal*_*pha 10

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

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

那就像你的NOW()那样代表时间.

但是IE10 推移在当前规范编者草案:

时间成为在此上下文中调用Performance接口now方法的结果.

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

因此,当你timePassed在IE10中第一次计算时,你会得到负面的43年.

幸运的是,因为传递给requestAnimationFrame回调的值在任何一种情况下都具有相同的单位,只是一个不同的参考点,你可以很容易地调整到这一点.

有三种可能性:

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

    // start the animation
    reqAnimationFrame(function (t) {
        previousTime = t - (NOW() - previousTime);
        animStep(t);
    );
    
    Run Code Online (Sandbox Code Playgroud)

    timePassed无论浏览器遵循哪个规范,这都将使计算(包括第一个)正确.并且因为它只改变了第一次调用,所以从长远来看,你也没有任何额外的开销.