Strange time behavior in javascript

I tried to implement kinetic scrolling (whether it is a good idea or not, this is not a question) and experienced some "strange" behavior.

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

The problem is that deltaTime often gets negative, what am I missing?

Edit: I am using Chromium Version 51.0.2704.79 Ubuntu 14.04 (64-bit) if that helps.

+6
source share
1 answer

As @Whothehellisthat already pointed out in his comment:

rAF timestamp is not very reliable

Here is a small example to read this:

 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> 

There is a workaround. You can use var timestamp = performance.now(); at the beginning of your method instead of getting a timestamp after rAF time.

Here is an example:

 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> 
+2
source

All Articles