Is there any way to measure the number of milliseconds between mouse press and release?
You could create a closure to share two variables, one to store the start time and other for the end time, then in the mouseup event, get the difference:
(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
};
})();
Check this working example.
tl;dr answer
- Get the time between two events by subtracting the
.timeStampproperty of the first event from the.timeStampproperty of the second event. - Don't ever try to get the time an event occurred by creating a
new Date()or callingDate.now()inside its handler. - Be aware that even if you follow this advice, you may occasionally get wildly inaccurate answers in some browsers (notably Edge), if the execution of your handlers is delayed by slow JavaScript unrelated to your handlers.
Longer answer
This is a much more subtle problem than other answers here give it credit for being.
The approach proposed by CMS's answer - of getting the time inside each handler by creating a new Date() and then subtracting these times from each other - has the potential to be grossly inaccurate. The problem with this approach is that you're not comparing the times at which the events occurred, you're comparing the times at which their handlers fired.
The article linked to by the question asker - John Resig's How JavaScript Timers Work - is relevant to understanding the problem here. JavaScript execution is single threaded, and whenever something outside of JavaScript triggers some JavaScript execution - whether it's a timeout firing, an event occurring, or a script loading - that JavaScript gets added to a queue of callbacks waiting to fire, which get executed sequentially. In most browsers, there's one JavaScript thread, and one queue, per browser tab. In Safari, there's one thread full stop, which is shared between all tabs - meaning that slow JavaScript in one tab can delay your event handlers from firing in another tab.
This leads to a couple of ways that our attempt to calculate the time between events can get horribly screwed up if we try to calculate it based upon the times that the handlers run. Consider the following two scenarios:
First scenario- Some computationally expensive JavaScript starts executing that will take 1 second to execute.
- The first event occurs (i.e. the user mouses down on the target element)
- 200 milliseconds later, the second event occurs (i.e. the user mouses up on the target element).
What happens next? The computationally expensive JavaScript finishes running, and then both event handlers fire in rapid succession. Consequently, if you are timing the events by getting the current time when the handler fires, you will wrongly calculate the time between the events to be close to 0 milliseconds.
Second scenario- The first event occurs and its handler fires. It stores the current time in a variable for later reference, and then starts doing some computation that will take 1 second to complete.
- 200 milliseconds after the first event is triggered, the second event is triggered.
What happens next? This time, of course, we will wrongly calculate the time between events as being approximately 1 second, because the second handler's execution gets delayed.
You can observe this in action at http://jsfiddle.net/gagLxrsc/. Just click the button and observe that the calculated time difference between mousedown and mouseup is always roughly 1000ms.
What can we do to stop this? Well, ideally, we want a way of getting the actual time an event occurred, not merely the time its handler fired. Does the DOM API offer us such a thing?
Maybe. It depends upon your browser. Events have a .timeStamp property, which, according to some people's interpretation of spec, should provide the time the event occurred rather than the time the handler fired. However, this is not currently reliably true across all browsers.
In Firefox, the .timeStamp property works the way we want it to - it gives a timestamp for when the mousedown or mouseup event occurred, rather than for when its handler began executing. In Edge, however, the .timeStamp property gives us the time the handler fired. (This was also the case in Chrome back when I first wrote this answer in 2014, but Chrome's behavior seems to have since been fixed.)
For browsers like Edge, there's nothing you can do to guarantee the correctness of the time differences you calculate between events, because you simply don't have access to any reliable information about when the event occurred. You may be able to mitigate the potential for inaccuracy by avoiding ever performing computationally expensive tasks that lock up the JavaScript thread - indeed, trying to do this is a good idea anyway, just to ensure your UI stays snappy and responsive and doesn't lag when the user hits a button. But if you fail at that, or if you're writing library or plugin code and don't know whether other JavaScript code on the page will do anything lengthy and expensive, then the risk of inaccuracy is unavoidable - you will simply have to tolerate it until such time as all browsers implement the timeStamp property the way that Firefox does. You still might as well use .timeStamp instead of new Date(), though, just to get more accurate results on the browsers that do implement .timeStamp properly.
Recap and examples
http://jsfiddle.net/gagLxrsc is a fiddle that calculates the time between a mousedown and mouseup on a button by creating a new Date() inside the event handlers. The first handler hot sleeps for a second after doing this, delaying the second handler from firing. In any browser, the calculated click duration will be approximately a second (i.e. it will be wrong).
http://jsfiddle.net/gagLxrsc/1/ is a modified version of the fiddle. The only change is that the time that events occurred is determined using the event's .timestamp property. In modern versions of Chrome, Firefox, or Safari, this fiddle calculates the duration of a click accurately, but in Edge it is still wrong.
When onmousedown is fired you can hang an onmouseup event on window. This will allow to avoid unnecessary closures.
el.onmousedown = function () {
var time = new Date(); //time in milliseconds
window.onmouseup=function(){
var diff=new Date()-time;
window.onmouseup=null;
}
};
check result here: http://jsbin.com/uneqo
Since the other links seem to be broken now, at least on chrome, here's a simple working demo:
var startTime;
window.startTimer = function() {
startTime = new Date();
}
window.reportTime = function() {
alert(new Date() - startTime)
}
<button onmousedown="startTimer()" onmouseup="reportTime()">Measure click time</button>
You can use two global variables to record the time of mousedown and mouseup, and have a substract
来源:https://stackoverflow.com/questions/1360818/how-to-measure-the-milliseconds-between-mousedown-and-mouseup