Fistright Fistright - 6 months ago 8
CSS Question

Time in mouse velocity tracker

Building a function to track the velocity of the mouse what Is the best time we can get?To build a function like this we have to do time/distance and to be more accurate usually in this type of function the date is taken.But what type of date?The time is taken until what point?Milliseconds or more?

Answer

In JavaScript on browsers, you have two options:

  1. Cross-browser, you can use Date.now() (or new Date().getTime() on really old ones) which gives you, at best, millisecond precision. The number you get is milliseconds-since-The-Epoch (Jan 1st 1970 at midnight, GMT) as a whole number. On many modern browsers, the resolution is indeed to-the-millisecond, but note that that may not be true for all browsers; RobG points out in a comment that some browsers have resolution as low as 15ms while others may be in the 3-4ms range. In my tests, Chrome 50, Firefox 46, and IE11 all provide to-the-millisecond resolution; IE8 only manages about 10ms resolution.

  2. If you only need to support fairly up-to-date browsers, you can use performance.now() (spec | MDN), which returns a DOMHighResTimeStamp which is a floating-point number which:

    ...SHOULD represent a time in milliseconds accurate to 5 microseconds...

    NOTE

    If the User Agent is unable to provide a time value accurate to 5 microseconds due to hardware or software constraints, the User Agent can represent a DOMHighResTimeStamp as a time in milliseconds accurate to a millisecond.

    So if the browser supports it, it is required to at least have millisecond resolution and ideally much, much better than that (via fractional values).

This snippet will test your current browser's Date object resolution (here's an off-site version that will work on older browsers like IE8):

(function() {
  "use strict";

  if (!Date.now) {
    Date.now = function() {
      return new Date().getTime();
    };
  }

  var testcount = document.getElementById("testcount");
  var resolution = document.getElementById("resolution");

  document.getElementById("the-button").onclick = function() {
    var sum = 0;
    var n = 0;

    log("Checking this browser's Date object resolution...");
    document.getElementById("results").style.display = "";
    setTimeout(batch, 50);

    function batch() {
      var target = n + 1000;
      while (n < target) {
        sum += test();
        ++n;
      }
      testcount.innerHTML = n;
      resolution.innerHTML = (sum / n) + "ms";
      if (n < 10000) {
        setTimeout(batch, 50);
      } else {
        log("Done");
      }
    }
  };

  function test() {
    var x = Date.now();
    var y;
    do {
      y = Date.now();
    } while (x == y);
    return y - x;
  }

  function log(msg) {
    var p = document.createElement("p");
    p.appendChild(document.createTextNode(msg));
    document.body.appendChild(p);
  }
})();
<input type="button" id="the-button" value="Test">
<div id="results" style="display: none">
  Tests so far: <span id="testcount">0</span>
  <br>Rough resolution: <span id="resolution"></span>
</div>

This snippet will test your current browser's performance.now() resolution, if it supports it:

(function() {
  "use strict";
  
  if (typeof performance !== "object" || !performance.now) {
    log("Your browser doesn't support performance.now()");
    return;
  }

  var testcount = document.getElementById("testcount");
  var resolution = document.getElementById("resolution");

  document.getElementById("the-button").onclick = function() {
    var sum = 0;
    var n = 0;

    log("Checking this browser's performance.now() resolution...");
    document.getElementById("results").style.display = "";
    setTimeout(batch, 50);

    function batch() {
      var target = n + 1000;
      while (n < target) {
        sum += test();
        ++n;
      }
      testcount.innerHTML = n;
      resolution.innerHTML = (sum / n) + "ms";
      if (n < 10000) {
        setTimeout(batch, 50);
      } else {
        log("Done");
      }
    }
  };

  function test() {
    var x = performance.now();
    var y;
    do {
      y = performance.now();
    } while (x == y);
    return y - x;
  }

  function log(msg) {
    var p = document.createElement("p");
    p.appendChild(document.createTextNode(msg));
    document.body.appendChild(p);
  }
})();
<input type="button" id="the-button" value="Test">
<div id="results" style="display: none">
  Tests so far: <span id="testcount">0</span>
  <br>Rough resolution: <span id="resolution"></span>
</div>