Можно ли измерить количество миллисекунд между нажатием и отпусканием мыши?
Как измерить миллисекунды между mousedown и mouseup?
Ответ 1
Вы можете создать закрытие для совместного использования двух переменных: одного для сохранения времени начала и другого для конечного времени, а затем в событии 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
};
})();
Проверьте этот рабочий пример.
Ответ 2
Обновление в декабре 2017 года: .timeStamp
, похоже, теперь корректно реализовано в Chrome, поэтому этот ответ является еще большим улучшением по сравнению с ответом CMS сегодня, чем когда я впервые написал его. Я уточню ответ более тщательно со временем; на данный момент оригинальный ответ - в комплекте с устаревшими утверждениями о том, что он не работает должным образом в Chrome, - сохраняется ниже строки.
tl; dr ответ
- Получить время между двумя событиями, вычитая свойство
.timeStamp
первого события из свойства.timeStamp
второго события, - Никогда не пытайтесь получить время, когда произошло событие, создав
new Date()
или вызывающийDate.now()
внутри своего обработчика. - Имейте в виду, что даже если вы будете следовать этому совету, иногда вы можете получать дико неточные ответы в некоторых браузерах, включая Chrome, если выполнение ваших обработчиков задерживается медленным JavaScript, не связанным с вашими обработчиками.
Более длинный ответ
Это гораздо более тонкая проблема, чем другие ответы здесь дают ему честь для бытия.
Подход предложенный ответом CMS - получения времени внутри каждого обработчика путем создания new Date()
, а затем вычитания этих времен друг от друга - имеет потенциал для быть грубым неточным. Проблема с этим подходом заключается в том, что вы не сравниваете время, в которое произошли события, вы сравниваете время, в которое их обработчики запускались.
В статье, связанной с вопросом - Джон Ресиг Как работают JavaScript-таймеры - имеет значение для понимания проблемы здесь. Выполнение JavaScript однопоточное, и всякий раз, когда что-то вне JavaScript запускает выполнение JavaScript - будь то тайм-аут, событие или загрузка script, что JavaScript добавляется в очередь обратных вызовов, ожидающих запуска, которые выполняются последовательно. В большинстве браузеров есть один поток JavaScript и одна очередь для каждой вкладки браузера. В Safari существует одна остановка потока, которая разделяется между всеми вкладками - это означает, что медленный JavaScript на одной вкладке может задерживать обработчики событий от запуска на другой вкладке.
Это приводит к двум путям, по которым наша попытка подсчитать время между событиями может быть ужасно привинчена, если мы попытаемся вычислить ее в зависимости от времени, которое выполняют обработчики. Рассмотрим следующие два сценария:
Первый сценарий- Выполняется несколько дорогостоящих JavaScript с вычислительными затратами, которые будут выполняться в течение 1 секунды.
- Первое событие происходит (т.е. пользователь опускается на целевой элемент)
- 200 миллисекунд позже, происходит второе событие (то есть пользователь нажимает на целевой элемент).
Что будет дальше? Вычислительный дорогостоящий JavaScript заканчивается, а затем оба обработчика событий срабатывают быстро. Следовательно, если вы синхронизируете события, получая текущее время при срабатывании обработчика, вы ошибочно вычисляете время между событиями, которое должно быть близко к 0 миллисекундам.
Второй сценарий- Первое событие происходит, и его обработчик срабатывает. Он сохраняет текущее время в переменной для последующей ссылки, а затем начинает выполнять некоторые вычисления, для завершения которых потребуется 1 секунда.
- 200 миллисекунд после запуска первого события, запускается второе событие.
Что будет дальше? На этот раз, конечно, мы ошибочно вычислим время между событиями как приблизительно 1 секунду, потому что выполнение второго обработчика задерживается.
Это можно увидеть в действии http://jsfiddle.net/gagLxrsc/. Просто нажмите кнопку и обратите внимание, что расчетная разница во времени между mousedown и mouseup всегда составляет примерно 1000 мс.
Что мы можем сделать, чтобы остановить это? Ну, в идеале, нам нужен способ получения фактического времени, когда произошло событие, а не просто время его увольнения. Предлагает ли DOM API нам такую вещь?
Может быть. Это зависит от вашего браузера. События имеют свойство .timeStamp
, которое, по мнению некоторых людей, интерпретирует спецификацию, должно предоставить время, когда произошло событие, а не время обработчик уволен. Однако в настоящее время это не достоверно верно во всех браузерах.
В Firefox свойство .timeStamp
работает так, как мы этого хотим, - оно дает отметку времени, когда произошло событие mousedown или mouseup, а не когда начался его обработчик. Однако в Chrome свойство .timeStamp
дает нам время, в которое ушел обработчик. Существует открытая ошибка в описании отслеживания ошибок, описывающая это поведение, в комплекте с утверждением о том, что поведение Chrome нарушает спецификацию, но никто не предпринял никаких действий так как он был открыт более 2 лет назад.
Для браузеров, таких как Chrome, вы ничего не можете сделать, чтобы гарантировать правильность расхождений во времени, которые вы вычисляете между событиями, потому что у вас просто нет доступа к какой-либо достоверной информации о том, когда произошло событие. Возможно, вы сможете уменьшить потенциальную неточность, избегая когда-либо выполняющих дорогостоящие задачи, зависящие от вычислительных ресурсов, которые блокируют поток JavaScript - действительно, попытка сделать это - хорошая идея, так или иначе, чтобы обеспечить постоянный и отзывчивый интерфейс пользователя и не отставать когда пользователь нажимает кнопку. Но если вы терпите неудачу, или если вы пишете библиотеку или код плагина и не знаете, будет ли другой код JavaScript на странице делать что-то длинное и дорогое, то риск неточности неизбежен - вам просто придется терпеть до тех пор, пока все браузеры не реализуют свойство timeStamp
так, как это делает Firefox. Вы по-прежнему могли бы использовать .timeStamp
вместо new Date()
, хотя, чтобы получить более точные результаты в браузерах, которые действительно реализуют .timeStamp
правильно.
Рекомендации и примеры
http://jsfiddle.net/gagLxrsc - это скрипка, которая вычисляет время между a mousedown
и mouseup
на кнопке, создавая new Date()
внутри обработчиков событий. Первый обработчик горячий спит в течение секунды после этого, задерживая второй обработчик от стрельбы. Как в Chrome, так и в Firefox, расчетная продолжительность клика будет примерно на секунду (т.е. Будет неправильной).
http://jsfiddle.net/gagLxrsc/1/ - это модифицированная версия скрипта. Единственное изменение заключается в том, что время, в которое произошли события, определяется с использованием свойства события .timeStamp
. В Firefox эта скрипка точно вычисляет длительность щелчка, но в Chrome все еще не так.
Ответ 3
Так как другие ссылки, кажется, сейчас сломаны, по крайней мере на хром, вот простая рабочая демонстрация:
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
Когда 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
Ответ 5
Вы можете использовать две глобальные переменные для записи времени mousedown и mouseup и иметь вычитание