【问题标题】:Using javascript setInterval function to achieve animate effect:slower than I expected使用javascript setInterval函数实现动画效果:比我预期的要慢
【发布时间】:2012-08-06 11:15:08
【问题描述】:

我想使用javascriptsetInterval函数来实现一个盒子旋转动画效果,我希望动画保持1.5秒,1.5秒内盒子会旋转360度,所以我以一毫秒计算增量,并使用setInterval函数每毫秒。这是我的代码:

var duration= 1500;//The animation duration time
var rotate = 360;//The rotate need to be rotate
var degPerSec = rotate / parseFloat(duration); //the increment per millisecond
var degree = 0;//the begin degree
console.time('rotate');
var timer = setInterval(function () {
    degree = degree + degPerSec;
    $('#test')[0].style.MozTransform = 'rotate(' + degree + 'deg)';
     $('#test')[0].style.WebkitTransform = 'rotate(' + degree + 'deg)';

    if (degree >= rotate) { //if reach 360 degree , clear the interval
        clearInterval(timer);
        console.timeEnd('rotate');// caculate the duration 
    }
    }, 1)
})

动画可以成功执行,但是好像不止1.5s,当我用console.time计算整个持续时间时,它持续了大约6s!不是1.5s。为什么会发生这种情况?我该如何解决这个问题?

这里是demo

更新:: 为什么我不使用css3:因为旋转度数是作为参数,需要在外部传递表单,尚未定义

【问题讨论】:

  • JavaScript 不保证计时器间隔,1ms 几乎是不可能的。请参阅 this article 以获得出色的解释。

标签: javascript animation setinterval


【解决方案1】:

当您可以使用简单的样式表时,您到底为什么要使用 Jquery 呢?您已经在使用 Mozilla 和 Webkit 特定的分支代码。还不如只用 CSS3 来完成它。速度更快(使用原生 C 代码而不是 JS)并且更简单。

#test{
    width:30px;
    height:30px;
    background:red;
    position:absolute;
    left:20px;
    top:20px;
    -webkit-transition: all 1.5s ease;
    -moz-transition: all 1.5s ease;
    -o-transition: all 1.5s ease;
    transition: all 1.5s ease;
}

编辑:如果您需要为旋转度数使用可变参数,使用 JS 仍然非常可行:

var degrees = 360;
var incrementer = 1;
setInterval(function() {
  var deg = "rotate(" + (degrees * incrementer) + "deg)";
  var obj = document.getElementById("test");
  if (typeof(obj.style.transform) !== "undefined") {
    obj.style.transform = deg;
  } else if (typeof(obj.style.MozTransform) !== "undefined") {
    obj.style.MozTransform= deg;
  } else if (typeof(obj.style.WebkitTransform) !== "undefined") {
   obj.style.WebkitTransform = deg;
  }
  incrementer = incrementer + 1;
}, 1500);

【讨论】:

  • 因为旋转度数作为参数应该从外部传递
  • 真的吗?所以this link 不起作用?因为它在我的系统上运行良好。
【解决方案2】:

这是因为您更改了 dom,然后会发生重新流动,并且重新流动会更新整个视图(需要一段时间)。要解决这个问题,要么减少更新频率,要么使用 css3 动画/过渡。

【讨论】:

    【解决方案3】:

    1 ms 间隔在某些操作系统(例如 Windows)上没有意义,因为那里的调度程序时间片约为 10 ms。此外,您的函数总共可能需要超过 1 毫秒。这两个人同意你的放缓。

    为了安全起见,您可以测量函数调用之间的实际延迟。

    【讨论】:

      【解决方案4】:

      你这样做有什么原因吗?为什么不直接使用transition 来定义转换的持续时间?

      ...
      -webkit-transform: rotate(360deg);  
      -webkit-transition:-webkit-transform 1s ease-in-out;  
      ...
      

      【讨论】:

      • 因为旋转度数作为参数应该从外部传递
      【解决方案5】:

      以上所有关于 css 使用的 cmets 都是正确的。还值得注意的是,每毫秒运行这么多代码太过分了——你只需要大约 30 帧/秒就可以让动画在人眼中流畅地显示,而这里你运行的是 1000 帧/秒。如果将帧间隔多一点并每隔约 33 毫秒运行一次动画,则动画会更快并且看起来更流畅。

      最后,有一个工具可以确定最佳帧速率并为我们执行内置在浏览器中的运行循环,称为requestAnimationFrame。您可以将此回调传递给它,它将确定最有效的帧速率(如果可能,通常为 60)并以最有效的方式运行动画,从而最大限度地减少与重绘相关的开销。

      对于此示例,只需将 setInterval 替换为 requestAnimationFrame 并稍微调整您的旋转值即可。

      【讨论】:

        猜你喜欢
        • 2016-08-21
        • 1970-01-01
        • 2020-12-04
        • 1970-01-01
        • 2012-07-21
        • 2018-03-02
        • 1970-01-01
        • 2018-03-09
        • 1970-01-01
        相关资源
        最近更新 更多