如何设置mousemove更新速度?

Vin*_*ent 17 html javascript refresh mousemove

我生成一个功能,它需要设置简单快速的签名.我正在画布领域写签名.我使用jQuery,但mousemove坐标的刷新率不够快.会发生的是,如果你快速写下签名,你会看到写入像素之间有一些空格.

如何更快地设置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);

}
Run Code Online (Sandbox Code Playgroud)

Pis*_*3.0 14

你不能.mousemove事件由浏览器生成,因此您可以像浏览器生成它们一样快地接收它们.

浏览器没有义务以任何给定的速率生成事件(通过移动的像素或经过的时间):如果您快速移动鼠标,您将看到报告中的"跳跃",因为浏览器正在报告"鼠标移动了,它现在在这里",而不是"......并经历了这些像素".实际上,慢速计算机上的浏览器可能会生成较少的mousemove事件,以免页面速度变慢.

你可以做的是用一条直线连接mousemove事件的连续位置 - 这显然不会让你更精确,但它可以减轻影响.


riv*_*ver 7

你需要让你的处理程序更快.

如果该事件的处理程序仍在运行,浏览器可以删除事件,因此您需要尽快退出mousemove处理程序.你可以尝试在那里优化代码或推迟工作直到鼠标移动完成.绘图可能是您正在做的最慢的事情,因此您可以将鼠标移动存储在内存中并稍后绘制.在绘图完成之前,这不会更新显示,但否则会更好.


Enr*_*iqe 7

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

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


小智 5

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

显然,大多数鼠标/指针每秒向操作系统报告其位置的次数少于 100 次,因此这可能甚至不在浏览器的控制范围内。

您可能想研究一下新PointerEvent.getCoalescedEvents()方法。来自 MDN 文档:

该接口getCoalescedEvents()的方法返回合并到调度事件中的PointerEvent所有实例的序列。PointerEventpointermove

这是一个例子:

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

然而,经过测试后,它似乎很少合并我计算机上的事件。不过,它在速度较慢的计算机上可能更有用。因此,目前最好的方法可能是使用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>
Run Code Online (Sandbox Code Playgroud)