有没有办法加速鼠标移动事件?

16

我为这个网站写了一个小绘图脚本(canvas):http://scri.ch/

当你点击文档时,每个 mousemove 事件基本上执行以下操作:
- 获取坐标。
- 在此点和前一个点之间使用 context.lineTo()
- context.stroke() 绘制线条。

正如您所看到的,如果您移动鼠标非常快,事件不会触发足够多次(取决于您的 CPU / 浏览器 / 等等),从而绘制一条直线。

伪代码如下:

window.addEventListener('mousemove', function(e){
  myContext.lineTo(e.pageX, e.pageY);
  myContext.stroke();
}, false);

这是一个已知的问题,现有解决方案是可以的,但我想优化它。

所以我不是每次鼠标移动时都调用stroke() ,而是将新坐标放入数组队列中,然后使用定时器定期绘制/清空该数组。

伪代码如下:

var coordsQueue = [];

window.addEventListener('mousemove', function(e){
  coordsQueue.push([e.pageX, e.pageY]);
}, false);

function drawLoop(){
  window.setTimeout(function(){
    var coords;
    while (coords = coordsQueue.shift()) {
      myContext.lineTo(coords[0], coords[1]);
    }
    myContext.stroke();
    drawLoop();
  }, 1000); // For testing purposes
}

但是这并没有改善线条。所以我尝试只在mousemove上绘制一个点。结果相同:点之间的间距太大了。

这让我意识到,第一个代码块已经足够高效了,只是mousemove事件触发得太慢了。

因此,在我自己花费了一些时间实现一个无用的优化之后,轮到你了:是否有一种方法可以优化DOM脚本中mousemove的触发速度?

是否可能随时“请求”鼠标位置?

感谢您的建议!


1
如何设置mousemove更新速度? - river
2个回答

21

如果您想增加报告频率,恐怕就没那么幸运了。小鼠每秒仅向操作系统报告它们的位置 n 次,我认为 n 通常少于100次。(如果有人可以用实际规格确认这一点,可以随意添加!)

因此,为了获得平滑的线条,您需要想出某种插值方案。关于这个主题有很多文献;我建议使用单调立方插值,因为它是本地的、易于实现和非常稳定的(没有过冲)。

然后,一旦您计算出样条曲线,就可以用足够短的线段来近似它,使它看起来平滑,或者您可以全力以赴地编写自己的Bresenham 算法来绘制它。

如果所有这些对于一个简单的绘图应用程序都值得,那当然是由您来决定的。


2
谢谢提供的链接,但是对于这个应用来说这有点过度杀鸡了。我认为问题不是来自于操作系统(Photoshop运行得很快),而是浏览器自愿限制了mousemove事件触发,肯定是因为很多脚本直接依赖它来执行密集型任务。但为什么不允许作者请求鼠标位置呢?可以像window.getMousePosition() 这样实现吗? - bpierre
SVG Edit(http://code.google.com/p/svg-edit/)是开源的,并且显然进行了一些平滑计算,因此您可能不需要重新发明轮子。 - jbrookover
2
普通鼠标每秒发送约100-150个更新。我的罗技G3发送500个。游戏鼠标可能会发送更多。 - Paul Groke

0
很酷的网站,不幸的是,JavaScript 没有请求当前鼠标位置的方法,你所拥有的唯一钩子就是你已经使用的事件。如果你必须要更多的控制,我建议你考虑使用 Flash,在那里你可以改变帧速率并请求鼠标位置。
trace("Mouse X: " + _xmouse);
trace("Mouse Y: " + _ymouse);

2
谢谢,但我不会使用Flash,我是一个开放标准的倡导者!;-) - bpierre
7
那么你就要受那些标准的支配 :-) - SavoryBytes
11
比起被Flash任意摆布,这要好得多。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接