如何设置mousemove更新速度?

发布于 2024-10-21 08:20:00 字数 330 浏览 5 评论 0原文

我生成一个函数,需要设置简单快速的签名。我正在画布字段中写签名。我使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

荒岛晴空 2024-10-28 08:20:00

你不能。 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.

骷髅 2024-10-28 08:20:00

您需要让您的处理程序更快。

如果该事件的处理程序仍在运行,则浏览器可以删除该事件,因此您需要尽快退出 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.

千年*琉璃梦 2024-10-28 08:20:00

我建议(详细说明@river的答案):

  1. 在mousemove事件处理程序中,只需将这些点(鼠标移动通过)保存到某个缓冲区(数组)中,使您的事件处理程序尽可能快地
  2. 创建另一个函数,该函数将从缓冲区读取这些点并绘制它在画布上作为 lineTo() -> lineTo() -> lineTo() 因此所有点都将被连接,它们之间没有空格。每次调用此函数时,它都会从缓冲区读取一些点并在它们之间画一条线。 (绘制后不要忘记从缓冲区中删除它们)
  3. 将此绘图函数分配给 setInterval() ,这样签名的绘制就不会等到用户完成“绘制”,而是会绘制该函数用户手指移动后签名有轻微延迟

I would suggest (detailing @river's answer):

  1. in mousemove event handler just save those points (mouse moves through) into some buffer (array) making your event handler as fast as possible
  2. make another function which will read those points from buffer and draw it on canvas as 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)
  3. assign this drawing function into a 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
手心的温暖 2024-10-28 08:20:00

其他一些答案表明这是因为处理程序函数速度较慢。在我的测试中,无论是在处理程序中使用 count++,还是使用更昂贵的画布绘制调用,都没有任何区别 - 在这两种情况下,10 秒内生成的事件数量约为 500 个。然而,它可能会在速度较慢的计算机上产生影响。

显然大多数鼠标/指针每秒向操作系统报告其位置的次数少于 100 次,因此这可能不是事实即使在浏览器的控制下。

您可能想查看新的 PointerEvent.getCoalescedEvents( ) 方法。来自 MDN 文档:

PointerEvent 接口的 getCoalescedEvents() 方法返回合并到分派的 pointermove 中的所有 PointerEvent 实例的序列 事件。

这是一个示例:

window.addEventListener("pointermove", function(event) {
  let events = event.getCoalescedEvents();
  for(let e of events) {
    draw(e.pageX, e.pageY);
  }
});

但是,经过测试后,它似乎很少合并我计算机上的事件。不过,它在速度较慢的计算机上可能更有用。因此,目前最好的方法可能是使用 ctx.lineTo 或类似的方法(也许是 arcTo)。这是一个简单的画布绘图演示,它将 getCoalescedEventslineTo 结合起来:

<canvas id="canvas" style="touch-action:none; width:100vw; height:100vh; position:fixed; top:0; left:0; right:0; bottom:0;"></canvas>

<script>
  let mouseIsDown = false;

  let ctx = canvas.getContext("2d");
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;


  window.addEventListener("pointerdown", function(e) {
    ctx.beginPath();
    ctx.moveTo(e.pageX, e.pageY);
    mouseIsDown = true;
  });
  window.addEventListener("pointerup", function(e) {
    mouseIsDown = false;
  });
  window.addEventListener("pointermove", function(event) {
   if(mouseIsDown) {
      let events = event.getCoalescedEvents();
      for(let e of events) {
        ctx.lineTo(e.pageX, e.pageY);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(e.pageX, e.pageY);
      }
   }
  });
</script>

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:

The getCoalescedEvents() method of the PointerEvent interface returns a sequence of all PointerEvent instances that were coalesced into the dispatched pointermove event.

Here's an example:

window.addEventListener("pointermove", function(event) {
  let events = event.getCoalescedEvents();
  for(let e of events) {
    draw(e.pageX, e.pageY);
  }
});

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 combines getCoalescedEvents with lineTo:

<canvas id="canvas" style="touch-action:none; width:100vw; height:100vh; position:fixed; top:0; left:0; right:0; bottom:0;"></canvas>

<script>
  let mouseIsDown = false;

  let ctx = canvas.getContext("2d");
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;


  window.addEventListener("pointerdown", function(e) {
    ctx.beginPath();
    ctx.moveTo(e.pageX, e.pageY);
    mouseIsDown = true;
  });
  window.addEventListener("pointerup", function(e) {
    mouseIsDown = false;
  });
  window.addEventListener("pointermove", function(event) {
   if(mouseIsDown) {
      let events = event.getCoalescedEvents();
      for(let e of events) {
        ctx.lineTo(e.pageX, e.pageY);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(e.pageX, e.pageY);
      }
   }
  });
</script>

时光倒影 2024-10-28 08:20:00

您可以根据计时器触发自己的事件,这可能是一个坏主意,但如果您确实需要它,总比什么都不做要好。

You can fire your own event based on timer, probably a bad idea but better then nothing if you really need it.

爱情眠于流年 2024-10-28 08:20:00

您是否尝试过使用 passive: truecapture: true 侦听器?通常浏览器会等待 preventDefault() 调用 50-200 毫秒,但使用 passive: true 选项将消除该行为,但代价是丢失 预防默认()。这种滞后就是为什么 @vageko4924 在 10 秒内看到总共约 500 个事件,尽管处理程序效率很高。 capture: true 选项只是确保您的回调在所有其他回调之前被触发 - 这可以保护您免受缓慢回调造成的间歇性延迟。

我不确定这在 jQuery 中会是什么样子,但它是在普通 JS 中:

let x = document.querySelector('#xx'); // which would be faster if it were using getElementById()
x.addEventListener('mousemove', e => {
    // Your logic here
}, {passive: true, capture: true});

来源:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Have you tried using a passive: true and capture: true listener? Usually browsers wait 50-200 ms for a preventDefault() call, but using the passive: true option will get rid of that behavior, at the cost of losing preventDefault(). This lag is why @vageko4924 saw about 500 events total in 10 seconds despite how efficient the handler was. The capture: 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:

let x = document.querySelector('#xx'); // which would be faster if it were using getElementById()
x.addEventListener('mousemove', e => {
    // Your logic here
}, {passive: true, capture: true});

Source: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文