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

24 javascript mouseevent

有没有办法测量鼠标按下释放之间的毫秒数?

CMS*_*CMS 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
    };

})();
Run Code Online (Sandbox Code Playgroud)

检查这个工作示例.

  • @jsoldi:它只是进行类型转换(到数字),有关详细信息,请参阅以下答案:http://stackoverflow.com/questions/1983040/what-does-the-new-mean-in-javascript/1983109# 1983109 (9认同)
  • `new Date()`之前的`+`是做什么的? (5认同)

Mar*_*ery 16

tl;博士回答

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

更长的答案

这是一个比其他答案更微妙的问题.

CMS的答案提出的方法- 通过创建a new Date()然后相互减去这些时间来获取每个处理程序内的时间- 可能非常不准确.这种方法的问题在于,您没有比较事件发生的时间,而是比较处理程序触发的时间.

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

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

第一种情况
  1. 一些计算成本昂贵的JavaScript开始执行,需要1秒才能执行.
  2. 第一个事件发生(即用户将鼠标放在目标元素上)
  3. 200毫秒后,第二个事件发生(即用户将鼠标放在目标元素上).

接下来发生什么?计算成本高昂的JavaScript完成运行,然后两个事件处理程序快速连续启动.因此,如果通过获取处理程序触发时的当前时间来对事件进行计时,则会错误地计算事件之间的时间,使其接近0毫秒.

第二种情况
  1. 第一个事件发生,其处理程序触发.它将当前时间存储在变量中供以后参考,然后开始执行一些需要1秒才能完成的计算.
  2. 触发第一个事件后200毫秒,触发第二个事件.

接下来发生什么?当然,这一次,我们错误地将事件之间的时间计算为大约1秒,因为第二个处理程序的执行被延迟了.

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

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

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

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

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

回顾和例子

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

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


Jon*_*nah 5

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

var startTime;

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


liu*_*all 0

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