精确检测鼠标坐标 [英] Detecting mouse coordinates with precision

查看:149
本文介绍了精确检测鼠标坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

睡了一夜后,我发现了一些关于这个问题的内容。我认为从根本上讲是令人难以置信的,至少对我而言。



鼠标坐标不精确(我想处理的速度很快在发生移动时必须重新创建整个画布),如上面的代码所示。我一块一块地测试了这段代码,发现问题不在我的循环中,但精度为

  if((newMouseX!== mouseX)&&(newMouseY!= = mouseY))。 

如果你用较慢的时间测试这部分代码(这将让你的眼睛发现差异)当'它停止'时坐标,然后你会发现 newMouseX & mouseX 关闭1-2像素90 %的时间,> 2像素的9%的时间,只相当于1%的时间。(我没有测量统计数据,但这是我在几轮测试中选择的)。



我无法在小提琴中使用它,但是我想你可以将它复制到你的试验场看看我的意思。如果你可以让它在小提琴中工作,那将是很好的,所以专家可以给它一个简短的:)



这意味着鼠标被我的代码视为移动,即使它应该停止,因此在它们之间停止几次,因此在一个循环中调用循环次数太多次了第二,这是我一直遇到的问题。



我很乐意听取其他专家的意见,包括那些可以测试并得出统计精确度/建议的人。



我的建议和目前的解决方案是在差异大于任一坐标的10个像素时考虑移动。当然这会带来一个问题,但我可以离开,直到一些更好的解决方案出现。



所以而不是

  if((newMouseX!== mouseX)&&(newMouseY!= = mouseY))

我用过

  if((Math.abs(newMouseX  -  mouseX)> 10)||(Math.abs(newMouseY!= mouseY)> 10))

另一件需要考虑的事情就是当它离开我的目标画布区域时如何处理鼠标位置...此刻看起来像一个无限的运动!



问题:



如何获得精确的鼠标坐标以便我可以比较 mouseX & newMouseX



谢谢。

解决方案

鼠标精度由硬件决定。例如,高精度鼠标会产生与内置鼠标垫不同的结果(更不用说触摸设备)。



然而,这不是你的问题代码和您的方案。您只是在收听 mousemove 事件。根据定义,它只会在您移动鼠标时抛出一个事件 - 因此新的鼠标位置永远不会与前一个位置相同。这是不可能的,应该100%关闭(除非你在检查之前触发两个+移动,最后一个回到第一个位置)。



通常一个人会听取 mousedown mouseup 事件以及它们不依赖鼠标移动触发。在所有可能的情况下,根据鼠标移动检测开始和停止被认为是不可能的。



你可以做出妥协并定义一个开始是什么以及什么是停止就是,即。如果鼠标在x毫秒后没有移动则被认为是停止(开始是第一次移动)。



这意味着每次你需要遵循这个规则需要检测停止。进行绘图成像,有时你快速绘制其他时间。或者,如何在不绘制任何东西的情况下将鼠标移动到新位置...鼠标按钮的发明有充分的理由: - )



该规则很快就会被证明是无用的(或者过于复杂,容易出现多个错误)。



对于画布外的鼠标位置,有几种方法可以解决这个问题。



您可以通过调用获取画布边界:

  var canvasRect = canvas.getBoundingClientRect(); 

给你 properties ,用于检查鼠标位于此矩形内部或外部的位置。



另一种方法是收听到canvas元素上的 mouseleave mouseenter 事件。



第三种是实际使用鼠标按钮。当你在canvas元素上按下鼠标按钮时,你设置了一个标志,所以 mousemove 会考虑事件。



这将是继续听,直到释放鼠标按钮。如果您在画布外释放它并使用画布 mouseup 事件,则不会检测到它。因此,您应该收听窗口 mouseup 事件,该事件将在任何一种情况下触发。



这也适用于 mousemove 事件。使用窗口事件将允许您在画布外记录位置。如果你不想这样做,你可以使用画布' mousemove ,它将在画布的边界处剪辑。



归结为:



使用 mousedown mousemove mouseup 组合的事件,你会没事的。所有这些事件都为鼠标位置提供 clientX clientY



如果可以的话 - 您也可以通过访问我的 easyCanvas项目进行测试并运行示例:

示例 - 鼠标事件详情



这将显示鼠标按下,移动和向上的详细信息(详细信息随其他信息一起扩展,但您至少可以验证鼠标位置 - 点击而不移动,您会看到鼠标位置完全相同)。 / p>

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.

解决方案

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).

这篇关于精确检测鼠标坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆