如何衡量mousedown和mouseup之间的毫秒数?

时间:2009-09-01 06:22:33

标签: javascript mouseevent

有没有办法测量鼠标发布之间的毫秒数?

6 个答案:

答案 0 :(得分:28)

您可以创建一个闭包来共享两个变量,一个用于存储开始时间,另一个用于结束时间,然后在mouseup事件中,获得差异:

(function () {
    var element = document.getElementById('element'),
        start, end;

    element.onmousedown = function () {
      start = +new Date(); // get unix-timestamp in milliseconds
    };


    element.onmouseup = function () {
      end = +new Date();

      var diff = end - start; // time difference in milliseconds
    };

})();

检查此工作example

答案 1 :(得分:15)

tl;博士回答

  • 通过从第二个事件的.timeStamp属性中减去第一个事件的.timeStamp属性来获取两个事件之间的时间。
  • 不要通过在其处理程序中创建new Date()或调用Date.now()来尝试获取事件发生的时间。
  • 请注意,即使您遵循此建议,如果处理程序的执行因与您的处理程序无关的慢速JavaScript而延迟,您可能偶尔会在某些浏览器(特别是Edge)中得到非常不准确的答案。

更长的答案

这是一个比其他答案更微妙的问题,因为它可以归功于。

方法proposed by CMS's answer - 通过创建new Date()然后从彼此中减去这些时间来获取每个处理程序中的时间 - 可能非常不准确。这种方法的问题在于,您没有比较事件发生的时间,而是在比较处理程序触发的时间。

提问者链接的文章 - John Resig的How JavaScript Timers Work - 与此处理解问题相关。 JavaScript执行是单线程的,只要JavaScript之外的某些东西触发了一些JavaScript执行 - 无论是超时触发,发生事件还是脚本加载 - JavaScript都会被添加到等待触发的回调队列中,这会得到顺序执行。在大多数浏览器中,每个浏览器选项卡都有一个JavaScript线程和一个队列。在Safari中,有一个线程完全停止,它在所有选项卡之间共享 - 这意味着一个选项卡中的慢速JavaScript可能会延迟您的事件处理程序在另一个选项卡中触发。

这导致了一些方法,如果我们尝试根据处理程序运行的时间来计算事件,我们尝试计算事件之间的时间可能会非常糟糕。请考虑以下两种情况:

第一种情况
  1. 一些计算成本昂贵的JavaScript开始执行,需要1秒才能执行。
  2. 发生第一个事件(即用户将鼠标放在目标元素上)
  3. 200毫秒后,第二个事件发生(即用户将鼠标放在目标元素上)。
  4. 接下来会发生什么?计算成本高昂的JavaScript完成运行,然后两个事件处理程序快速连续启动。因此,如果您通过获取处理程序触发时的当前时间来对事件进行计时,则会错误地计算事件之间的时间,使其接近0毫秒。

    第二种情况
    1. 发生第一个事件并触发其处理程序。它将当前时间存储在变量中供以后参考,然后开始进行一些需要1秒才能完成的计算。
    2. 触发第一个事件后200毫秒,触发第二个事件。
    3. 接下来会发生什么?当然,这一次,我们错误地将事件之间的时间计算为大约1秒,因为第二处理程序的执行被延迟了。

      您可以在http://jsfiddle.net/gagLxrsc/处观察此操作。只需单击按钮,观察mousedown和mouseup之间计算的时间差总是大约1000ms。

      我们可以做些什么来阻止这种情况?好吧,理想情况下,我们想要一种方法来获取事件发生的实际时间,仅仅是其处理程序触发的时间。 DOM API是否为我们提供了这样的东西?

      可能。这取决于您的浏览器。事件具有.timeStamp属性,根据某些人对规范的解释,该属性应该提供事件发生的时间而不是处理程序触发的时间。但是,目前在所有浏览器中都不可行。

      在Firefox中,.timeStamp属性按我们希望的方式工作 - 它为mousedown或mouseup事件发生时提供时间戳,而不是在其处理程序开始执行时。但是,在Edge中,.timeStamp属性为我们提供了处理程序触发的时间。 (当我在2014年第一次写这个答案时,Chrome也出现了这种情况,但Chrome的行为似乎已经修复了。)

      对于像Edge这样的浏览器,您无法保证事件之间计算时差的正确性,因为您无法访问任何可靠有关事件发生的时间的信息。您可以通过避免执行锁定JavaScript线程的计算成本高昂的任务来减少不准确的可能性 - 事实上,尝试执行此操作无论如何,只是为了确保您的UI保持活泼当用户按下按钮时,响应并且不会延迟。但是如果你失败了,或者你正在编写库或插件代码并且不知道页面上的其他JavaScript代码是否会做任何冗长和昂贵的事情,那么不准确的风险是不可避免的 - 你会只需要容忍它,直到所有浏览器都像Firefox那样实现timeStamp属性。不过,您仍然可以使用.timeStamp代替new Date(),只是为了在 正确实施.timeStamp的浏览器上获得更准确的结果。

      回顾和例子

      http://jsfiddle.net/gagLxrsc是一个小提琴,它通过在事件处理程序中创建mousedown来计算按钮上mouseupnew Date()之间的时间。第一个处理程序在执行此操作后会休眠一秒钟,从而延迟第二个处理程序的触发。在任何浏览器中,计算的点击持续时间大约为一秒(即它将是错误的)。

      http://jsfiddle.net/gagLxrsc/1/是小提琴的修改版本。唯一的变化是事件发生的时间是使用事件的.timestamp属性确定的。在Chrome,Firefox或Safari的现代版本中,这个小提琴准确地计算了点击的持续时间,但在Edge中它仍然是错误的。

答案 2 :(得分:5)

当onmousedown被解雇时,您可以在窗口挂起onmouseup事件。这样可以避免不必要的关闭。

el.onmousedown = function () {
  var time = new Date(); //time in milliseconds
  window.onmouseup=function(){
    var diff=new Date()-time;
    window.onmouseup=null;
  }
};

在此处查看结果:http://jsbin.com/uneqo

答案 3 :(得分:4)

由于现在其他链接似乎已被破坏,至少在chrome上,这是一个简单的工作演示:

var startTime;

window.startTimer = function() {
    startTime = new Date();
}
window.reportTime = function() {
	alert(new Date() - startTime)
}
<button onmousedown="startTimer()" onmouseup="reportTime()">Measure click time</button>

答案 4 :(得分:0)

您可以使用两个全局变量来记录mousedown和mouseup的时间,并有一个substract

答案 5 :(得分:0)

我认为这是最优雅的方式:

 function onMouseDown(e) {
    window.onmouseup = function(e2) {
      var diff = e2.timeStamp - e.originalEvent.timeStamp;
      console.log(diff);
      window.onmouseup = null;
    };
  }