2016-08-09 12 views
6

Próbowałem wprowadzić kinetyczne przewijanie (czy to dobry pomysł, czy nie jest to kwestia) i doświadczyłem "dziwnego" zachowania.Dziwne zachowanie w czasie w 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(); 
     }); 

Problemem jest to, że często deltaTime staje się ujemny, co mi brakuje?

Edytuj: Używam wersji Chromium 51.0.2704.79 Ubuntu 14.04 (64-bit), jeśli to pomaga.

+3

Zasadniczo, datownik rAF nie jest bardzo niezawodny. Wygląda na to, że przyciąga do najbliższej ramki, a nie do czasu, w którym kod jest faktycznie uruchamiany. Nigdy nie doszedłem do sedna, ale [miałem ten sam problem] (http://stackoverflow.com/questions/38360250/requestanimationframe-now-vs-performance-now-time-discrepancy). Uciekłem po prostu używając 'performance.now()' każdej klatki zamiast polegania na znaczniku czasu rAF. – Whothehellisthat

Odpowiedz

2

Jak @Whothehellisthat podkreślił już w swoim komentarzu:

datownik rAF nie jest bardzo niezawodny

Oto mały przykład, aby udowodnić, że:

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); 
 
}
<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>

Istnieje proste rozwiązanie. Możesz użyć metody var timestamp = performance.now(); na początku metody, zamiast otrzymywać znacznik czasu przez czas rAF.

Herezje przykład roboczych:

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); 
 
}
<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>