如何设置mousemove更新速度?
我生成一个函数,需要设置简单快速的签名。我正在画布字段中写签名。我使用jQuery,但是mousemove坐标的刷新速度不够快。发生的情况是,如果您快速书写签名,您会在书写像素之间看到一些空白。
如何设置鼠标移动的刷新速度更快?
$("#xx").mousemove(function(e){
ctx.fillRect(e.pageX - size, e.pageY - size, size, size);
$("#pagex").html(e.pageX - size);
$("#pagey").html(e.pageY - size);
}
im generating a function where it needs to set easy and fast a signature. I'm writing the signature in an canvas field. I use jQuery for it, but the refresh rate of mousemove coordinates is not fast enough. What happens is that if you write your signature to fast, you see some white spaces between writed pixels.
How can I set the refresh speed of the mousemove faster?
$("#xx").mousemove(function(e){
ctx.fillRect(e.pageX - size, e.pageY - size, size, size);
$("#pagex").html(e.pageX - size);
$("#pagey").html(e.pageY - size);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你不能。 mousemove 事件是由浏览器生成的,因此您接收它们的速度与浏览器生成它们的速度一样快。
浏览器没有义务以任何给定的速率(通过移动的像素或经过的时间)生成事件:如果快速移动鼠标,您将看到报告的坐标“跳跃”,就像浏览器报告的那样“鼠标已经移动,它现在在这里”,而不是“......并穿过这些像素”。事实上,速度较慢的计算机上的浏览器可能会生成较少的鼠标移动事件,以免页面速度变慢。
您可以做的是将 mousemove 事件的连续位置与直线连接起来 - 这显然不会让您获得任何更高的精度,但它可能会减轻影响。
You can't. The mousemove events are generated by the browser, and thus you are receiving them as fast as the browser is generating them.
The browser is not obliged to generate the events at any given rate (either by pixels moved, or by time elapsed): if you move the mouse quickly, you will see that a "jump" in coordinates is reported, as the browser is reporting "the mouse has moved, and it is now here", not "...and went through these pixels". In fact, a browser on a slow computer might generate fewer mousemove events, lest the page slow down to a crawl.
What you could do is to connect successive positions from mousemove events with a straight line - this will obviously not get you any more precision, but it may mitigate the impact.
您需要让您的处理程序更快。
如果该事件的处理程序仍在运行,则浏览器可以删除该事件,因此您需要尽快退出 mousemove 处理程序。您可以尝试优化那里的代码或将工作推迟到鼠标移动完成之后。绘图可能是您正在做的最慢的事情,因此您可以将鼠标移动存储在内存中并稍后绘制。在绘图完成之前,这不会更新显示,但否则效果会更好。
You need to make your handler faster.
Browsers can drop events if a handler for that event is still running, so you need to get out of the mousemove handler asap. You could try to optimise the code there or defer work till after the mouse movement is complete. Drawing is probably the slowest thing you are doing, so you could store the mouse movements in memory and draw later. This would not update the display until drawing had finished but it would otherwise work better.
我建议(详细说明@river的答案):
lineTo()
->lineTo()
->lineTo()
因此所有点都将被连接,它们之间没有空格。每次调用此函数时,它都会从缓冲区读取一些点并在它们之间画一条线。 (绘制后不要忘记从缓冲区中删除它们)setInterval()
,这样签名的绘制就不会等到用户完成“绘制”,而是会绘制该函数用户手指移动后签名有轻微延迟I would suggest (detailing @river's answer):
lineTo()
->lineTo()
->lineTo()
so all points will be connected, no whitespace between them. Every time you call this function, it will read few points from buffer and draw a line between them. (don't forget to delete them from buffer after drawing)setInterval()
so the drawing of your signature will not wait until user finished "drawing", but it will draw that signature with some slight delay after user's finger movements其他一些答案表明这是因为处理程序函数速度较慢。在我的测试中,无论是在处理程序中使用
count++
,还是使用更昂贵的画布绘制调用,都没有任何区别 - 在这两种情况下,10 秒内生成的事件数量约为 500 个。然而,它可能会在速度较慢的计算机上产生影响。显然大多数鼠标/指针每秒向操作系统报告其位置的次数少于 100 次,因此这可能不是事实即使在浏览器的控制下。
您可能想查看新的
PointerEvent.getCoalescedEvents( )
方法。来自 MDN 文档:这是一个示例:
但是,经过测试后,它似乎很少合并我计算机上的事件。不过,它在速度较慢的计算机上可能更有用。因此,目前最好的方法可能是使用 ctx.lineTo 或类似的方法(也许是 arcTo)。这是一个简单的画布绘图演示,它将
getCoalescedEvents
与lineTo
结合起来:Some other answers suggested that it's because of a slow handler function. In my tests it didn't make any difference whether I just had
count++
in the handler, or much more expensive canvas draw calls - the number of events generated in 10 seconds was about 500 in both cases. However, it might have made a difference on a slower computer.Apparently most mice/pointers only report their position to the OS fewer than 100 times per second, so this may be something that's not even in the browser's control.
You may want to look into the new
PointerEvent.getCoalescedEvents()
method. From the MDN docs:Here's an example:
However, after testing this, it only rarely seems to coalesce the events on my computer. Again, though, it may be more useful on slower computers. So for now the best approach is probably to use
ctx.lineTo
, or a similar method (arcTo
, perhaps). Here's a simple working canvas drawing demo that combinesgetCoalescedEvents
withlineTo
:您可以根据计时器触发自己的事件,这可能是一个坏主意,但如果您确实需要它,总比什么都不做要好。
You can fire your own event based on timer, probably a bad idea but better then nothing if you really need it.
您是否尝试过使用
passive: true
和capture: true
侦听器?通常浏览器会等待preventDefault()
调用 50-200 毫秒,但使用passive: true
选项将消除该行为,但代价是丢失预防默认()。这种滞后就是为什么 @vageko4924 在 10 秒内看到总共约 500 个事件,尽管处理程序效率很高。
capture: true
选项只是确保您的回调在所有其他回调之前被触发 - 这可以保护您免受缓慢回调造成的间歇性延迟。我不确定这在 jQuery 中会是什么样子,但它是在普通 JS 中:
来源:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
Have you tried using a
passive: true
andcapture: true
listener? Usually browsers wait 50-200 ms for apreventDefault()
call, but using thepassive: true
option will get rid of that behavior, at the cost of losingpreventDefault()
. This lag is why @vageko4924 saw about 500 events total in 10 seconds despite how efficient the handler was. Thecapture: true
option just ensures your callback is fired before all others - this protects you from intermittent lag from slow callbacks.I'm not sure what this would look like in jQuery, but here it is in vanilla JS:
Source: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener