问题
After a sleepness night I discovered something about this question which I think is fundamentally mind boggling, at least to me.
Mouse coordinates ARE NOT PRECISE (I guess at a high speed of processing where the whole canvas has to be recreated when movement occurs) as in my codes above. I have tested this code piece by piece and discovered that the problem is not in my loop, but in the precision of
if ((newMouseX !== mouseX) && (newMouseY !== mouseY)).
If you tested this part of code by slower times (which will allow your eyes to detect the difference in coordinates when 'it stops', then you will realise that newMouseX & mouseX are off by 1-2 pixel 90% of the time, > 2 pixel 9% of the time, and only equal about 1% of the time. (I did not measure the statistics but that is what I picked on several rounds of testing).
I can't get it to work in fiddle but I think you can copy it to your testing ground to see what I mean. If you can get it to work in fiddle it would be great so experts can give it a short :)
This means that the mouse is considered to be 'moving' by my code even when it should have 'stopped', and thus 'stops' several times in between, therefore calling the loop too many times in a second, which is the problem I have been having.
I would be happy to hear comments from other experts, including those who can test this and come up with a statistical precision/advice.
My advice, and solution for the moment, is to consider movement when the difference is more than 10 pixels of either coordinates. Of course this presents a problem, but I can leave with that until some better solution comes up.
so instead of
if ((newMouseX !== mouseX) && (newMouseY !== mouseY))
i have used
if (( Math.abs(newMouseX - mouseX) > 10) || ( Math.abs(newMouseY != mouseY) > 10) )
Another thing to consider is how to deal with the mouse position when it goes off my target canvas area... that looks like an infinite movement at the moment!
The Question:
How can I get the precise mouse coordinates so I can compare mouseX & newMouseX?
Thanks.
回答1:
Mouse precision is determined by the hardware. A high-precision mouse will produce different results than a built-in mouse pad for instance (not to mention touch devices).
However, this is not the problem with your code and your scenario. You are only listening to the mousemove event. It will by definition only throw an event when you move the mouse - hence the new mouse position can never be at the same position as the previous one. That would be impossible and should be off by 100% (unless you are triggering two+ moves where the last goes back to the fist position before you check).
Normally one would listen to the mousedown and mouseup events as well as they are not dependent on a mouse move to trigger. Detecting start and stop solely based on mouse movement is considered impossible under all possible circumstances.
You can do a compromise and make a definition of what a start is and what a stop is, ie. if the mouse has not moved after x milliseconds it is considered a stop (start would be on first move).
This means you will need to follow this rule every time you need to detect a stop. Imaging doing a drawing and sometimes you draw sometime slow other times fast. Or, how do you move the mouse to a new position without drawing anything... There is a good reason for the mouse button(s) to be invented :-)
The rule will soon prove to be useless (or overly complicated prone to more than one error).
As to mouse positions outside canvas there are several ways to handle this.
You can get the canvas bounds by calling:
var canvasRect = canvas.getBoundingClientRect();
which gives you properties to check when mouse position is inside or outside this rectangle.
Another way is to listen to the mouseleave and mouseenter events on the canvas element.
A third is to actually use the mouse buttons. When mouse button is held down on the canvas element you set a flag so mousemove events are considered.
This will keep listening until the mouse button is released. If you release it outside canvas and is using the canvas mouseup event it won't be detected. Therefor you should listen to the window's mouseup event which will trigger in either case.
This also goes for mousemove events. Using the window event will allow you to record positions outside canvas. If you don't want to do this you can use canvas' mousemove which will clip at the canvas' boundaries.
It boils down to:
Use the mousedown, mousemove and mouseup events in combination and you'll be fine. All these events delivers clientX and clientY for mouse positions.
And if I may - you can also test by going to my easyCanvas project and run the sample:
Sample - mouse event details
This will show you details for mouse down, move and up (the details are extended with other information, but you can at least verify mouse positions - do a click without moving and you see the mouse position is exactly the same).
回答2:
http://jsfiddle.net/6czap/74/
I hope i helped with this :)
$("div").mousemove(function(e){
var pageCoords = "( " + e.pageX + ", " + e.pageY + " )";
var clientCoords = "( " + e.clientX + ", " + e.clientY + " )";
$("span:first").text("( e.pageX, e.pageY ) : " + pageCoords);
$("span:last").text("( e.clientX, e.clientY ) : " + clientCoords);
});
来源:https://stackoverflow.com/questions/17678288/detecting-mouse-coordinates-with-precision