Как измерить миллисекунды между mousedown и mouseup? - PullRequest
23 голосов
/ 01 сентября 2009

Можно ли измерить количество миллисекунд между мышью , нажмите и , отпустите ?

Ответы [ 5 ]

28 голосов
/ 01 сентября 2009

Вы можете создать замыкание, чтобы разделить две переменные: одну для хранения времени начала и другую для времени окончания, а затем в событии 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
    };

})();

Проверить это работает пример .

15 голосов
/ 17 декабря 2014

тл; д-р ответ

  • Получите время между двумя событиями, вычтя свойство .timeStamp первого события из свойства .timeStamp второго события.
  • Никогда не пытайтесь узнать время, когда произошло событие, создав new Date() или вызвав Date.now() внутри его обработчика.
  • Имейте в виду, что даже если вы будете следовать этому совету, вы можете время от времени получать дико неточные ответы в некоторых браузерах (особенно Edge), если выполнение ваших обработчиков задерживается из-за медленного JavaScript, не связанного с вашими обработчиками.

Более длинный ответ

Это гораздо более тонкая проблема, чем другие ответы, которые можно найти здесь.

Подход , предложенный ответом CMS - получить время внутри каждого обработчика путем создания new Date() и затем вычесть это время друг из друга - потенциально может быть неточным. Проблема с этим подходом состоит в том, что вы не сравниваете время, в которое события произошли , вы сравниваете время, в которое их обработчики срабатывали.

Статья, на которую ссылается вопроситель - Джон Резиг Как работают таймеры JavaScript - имеет отношение к пониманию проблемы здесь. Выполнение JavaScript является однопоточным, и всякий раз, когда что-то вне JavaScript вызывает некоторое выполнение JavaScript - будь то срабатывание тайм-аута, событие или загрузка скрипта - JavaScript добавляется в очередь обратных вызовов, ожидающих срабатывания, которые выполняются последовательно. В большинстве браузеров для каждой вкладки браузера имеется один поток JavaScript и одна очередь. В Safari есть точка полного останова потока, которая используется всеми вкладками. Это означает, что медленный JavaScript на одной вкладке может задержать запуск обработчиков событий на другой вкладке.

Это приводит к нескольким способам, которыми наша попытка вычислить время между событиями может быть ужасно обречена, если мы попытаемся вычислить его на основе времени, которое выполняются обработчиками. Рассмотрим следующие два сценария:

Первый сценарий
  1. Некоторые вычислительно дорогие JavaScript начинают выполняться, для выполнения которых требуется 1 секунда.
  2. Первое событие происходит (т. Е. Пользователь наводит курсор на целевой элемент)
  3. 200 миллисекунд спустя, происходит второе событие (т. Е. Пользователь подгоняет целевой элемент).

Что будет дальше? Завершает выполнение дорогой в вычислительном отношении JavaScript, и затем оба обработчика событий срабатывают быстро . Следовательно, если вы синхронизируете события, получая текущее время, когда обработчик срабатывает, вы ошибочно рассчитаете время между событиями, чтобы оно было близко к 0 миллисекундам.

Второй сценарий
  1. Первое событие происходит, и его обработчик срабатывает. Он сохраняет текущее время в переменной для последующего использования, а затем начинает выполнять вычисления, для завершения которых потребуется 1 секунда.
  2. 200 миллисекунд после запуска первого события, запускается второе событие.

Что будет дальше? На этот раз, конечно, мы будем ошибочно вычислять время между событиями как приблизительно 1 секунду, потому что выполнение обработчика second задерживается.

Вы можете наблюдать это в действии на http://jsfiddle.net/gagLxrsc/. Просто нажмите кнопку и обратите внимание, что расчетная разница во времени между mousedown и mouseup всегда составляет примерно 1000 мс.

Что мы можем сделать, чтобы остановить это? Ну, в идеале, мы хотим получить способ узнать фактическое время, когда произошло событие, , а не , просто время, когда его обработчик сработал. Предлагает ли нам DOM API такую ​​вещь?

Может быть. Это зависит от вашего браузера. У событий есть свойство .timeStamp, которое, согласно интерпретации спецификаций некоторых людей, должно предоставлять время, когда событие произошло, а не время, когда обработчик сработал. Однако в настоящее время это не совсем так во всех браузерах.

В Firefox свойство .timeStamp работает так, как нам нужно - оно дает метку времени для события mousedown или mouseup, а не для того, когда его обработчик начал выполняться. Однако в Edge свойство .timeStamp дает нам время запуска обработчика. (Так было и в Chrome, когда я впервые написал этот ответ в 2014 году, но поведение Chrome, похоже, с тех пор исправлено.)

Для таких браузеров, как Edge, вы ничего не можете сделать, чтобы гарантировать правильность разницы во времени, которую вы рассчитываете между событиями, потому что у вас просто нет доступа к надежной информации о том, когда произошло событие. Вы можете уменьшить вероятность неточности, избегая когда-либо выполнения дорогостоящих в вычислительном отношении задач, которые блокируют поток JavaScript - действительно, попытка сделать это - хорошая идея в любом случае , просто чтобы гарантировать, что ваш пользовательский интерфейс остается быстрым и отзывчивый и не лагает, когда пользователь нажимает кнопку. Но если у вас ничего не получится или вы пишете код библиотеки или плагина и не знаете, будет ли другой код JavaScript на странице делать что-то длинное и дорогое, риск неточности неизбежен - вам просто придется мириться до тех пор, пока все браузеры не реализуют свойство timeStamp так, как это делает Firefox. Тем не менее, вы все равно можете использовать .timeStamp вместо new Date(), чтобы получить более точные результаты в браузерах, которые do правильно реализуют .timeStamp.

Резюме и примеры

http://jsfiddle.net/gagLxrsc - это скрипка, которая вычисляет время между mousedown и mouseup на кнопке путем создания new Date() внутри обработчиков событий. После этого первый обработчик горячо спит в течение секунды, задерживая запуск второго обработчика. В любом браузере рассчитанная длительность клика будет составлять примерно секунду (т. Е. Она будет неправильной).

http://jsfiddle.net/gagLxrsc/1/ является модифицированной версией скрипки. Единственное изменение заключается в том, что время возникновения событий определяется с помощью свойства .timestamp события. В современных версиях Chrome, Firefox или Safari эта скрипка точно рассчитывает длительность щелчка, но в Edge она все равно неверна.

4 голосов
/ 05 июня 2016

Поскольку другие ссылки, похоже, сейчас не работают, по крайней мере, в 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 голосов
/ 01 сентября 2009

Когда срабатывает 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

0 голосов
/ 01 сентября 2009

Вы можете использовать две глобальные переменные, чтобы записать время mousedown и mouseup, и иметь субстракт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...