javascript中的奇怪计时行为

时间:2016-08-09 10:46:01

标签: javascript

我正在尝试实施动态滚动(无论这个好主意与否都不是问题)并且经历了一些"奇怪的"行为。

function scroll(timestamp){
    var deltaTime = timestamp - this.scrollLastTime;
    this.scrollLastTime = timestamp;
    console.log(deltaTime);
    var newPosition = this.scrollTop + this.scrollSpeed*deltaTime;
    if(newPosition <= 0){
      this.scrollTop = 0;
      this.scrolling = false;
      return;
    }else if(newPosition > this.scrollHeight-this.clientHeight){
      this.scrollTop = this.scrollHeight-this.clientHeight;
      this.scrolling = false;
    }else{
      this.scrollTop = newPosition;
      var newSpeed = this.scrollSpeed + Math.sign(this.scrollSpeed) * this.scrollAcceleration*deltaTime;
      if(this.scrollSpeed < 0 && newSpeed >= 0){
        this.scrolling = false;
      }else if(this.scrollSpeed >0 && newSpeed <= 0){
        this.scrolling = false;
      }else{
        this.scrollSpeed = newSpeed;
        window.requestAnimationFrame(this.scrollCallback);
      }
    }
  }
  document.getElementById("0").addEventListener('wheel',
        function(e){
            this.scrollSpeed = e.wheelDelta/100;
            if(!this.scrolling){
              this.scrolling = true;
              this.scrollLastTime = performance.now();
              this.scrollAcceleration = -0.01;
              if(!this.scrollCallback)this.scrollCallback = scroll.bind(this);
              window.requestAnimationFrame(this.scrollCallback);
            }
            e.preventDefault();
        });

问题是 deltaTime 经常变为负数,我缺少什么?

编辑:如果有帮助,我正在使用Chromium版本51.0.2704.79 Ubuntu 14.04(64位)。

1 个答案:

答案 0 :(得分:2)

正如@Whothehellist已经在他的评论中指出的那样:

  

rAF时间戳不是非常可靠

这是一个证明:

的小例子

&#13;
&#13;
document.getElementById("button").addEventListener('click', function(e){
        this.valueOfPerformanceNow = performance.now();
        if(!this.clickCallback)this.clickCallback = printTime.bind(this);
        window.requestAnimationFrame(this.clickCallback);
});

function printTime(timestamp){
  $("#perfromanceNow").val(this.valueOfPerformanceNow);
  $("#delta").val(timestamp-this.valueOfPerformanceNow);
  $("#timestamp").val(timestamp);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <input type="submit" id="button" value="print current time"><br>
  <label>performance.now():</label>
  <input type="text" id="perfromanceNow" readonly><br>
  <label>timestamp:</label>
  <input type="text" id="timestamp" readonly><br>
   <label>delta:</label>
  <input type="text" id="delta" readonly>
<div>
&#13;
&#13;
&#13;

有一个简单的解决方法。您可以在方法开头使用var timestamp = performance.now();,而不是通过rAF时间获取时间戳。

这是一个有效的例子:

&#13;
&#13;
document.getElementById("button").addEventListener('click', function(e){
        this.valueOfPerformanceNow = performance.now();
        if(!this.clickCallback)this.clickCallback = printTime.bind(this);
        window.requestAnimationFrame(this.clickCallback);
});

function printTime(){
  var timestamp = performance.now();
  $("#perfromanceNow").val(this.valueOfPerformanceNow);
  $("#delta").val(timestamp-this.valueOfPerformanceNow);
  $("#timestamp").val(timestamp);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <input type="submit" id="button" value="print current time with new timestamp initialization"><br>
  <label>performance.now():</label>
  <input type="text" id="perfromanceNow" readonly><br>
  <label>timestamp:</label>
  <input type="text" id="timestamp" readonly><br>
   <label>delta:</label>
  <input type="text" id="delta" readonly>
<div>
&#13;
&#13;
&#13;