jQuery mousemove性能 – 节流事件?

我们正面临着与mousemove连接的jQuery事件传播性能的问题:

我们有一个屏幕填充canvas,需要跟踪用户是否在其上拖动鼠标,因此我们在该对象上添加了一个鼠标移动侦听器,如下所示:

ourCanvas.on('mousemove', function(event) { event.preventDefault(); //our drag code here } }); 

此代码工作正常,但我们在一个测试系统上的当前Firefox(24)中遇到了严重的性能问题。 分析器告诉我们,大部分时间花在jQuery.event.dispatch() (我们尝试了当前最新的jQuery 1.8,1.9,1.10和2.0)。

我们通过在这里使用“jQuery.event.fix()”性能优化成功地减少了在dispatch()函数中花费的时间: http : //bitovi.com/blog/2012/04/faster-jquery-event-fix。 html但该测试系统的性能仍远低于我们的预期。

经过一些进一步的测试,我设法将其固定在系统上使用的鼠标上:它使用1000Hz 。 我们将用过的鼠标切换到125Hz并且瞧瞧,性能非常好。

我们的假设是,鼠标上的高Hz率引起了很多mousemove事件,因此我们更改了上面的代码以应用事件限制并且每隔X毫秒只调用事件处理:

 var lastMove = 0; var eventThrottle = 1; ourCanvas.on('mousemove', function(event) { event.preventDefault(); var now = Date.now(); if (now > lastMove + eventThrottle) { lastMove = now; //our drag code here } } }); 

它就像一个魅力,表现很棒。 即使我们只跳过两毫秒的事件。

现在我有两个问题:

  1. 我们有其他位置将mousemove监听器连接到不同的HTML元素, 我想将这个手工制作的节流管添加到所有这些mousemove处理程序中 ,以免再次遇到问题。 这在jQuery(2.0.3)中以某种方式可行吗? 我已经在jQuery javascript中看到了preDispatch钩子,但它们已经在调用fix()之后,它也使用了一些时间,我也想保存该调用。

  2. 令我感到困惑的是,已经有2ms的eventThrottle足以获得非常好的性能,所以我添加了一个计数器来查看有多少事件被跳过。 令人惊讶的结果是:它只跳过0-1个事件……在100ms的节流下,跳过的事件大约为60-70,所以如果每ms有少于1个mousemove事件,为什么这个代码有这样的毕竟是积极的影响?

感谢任何评论,克里斯托弗

在2015年底,我遇到了我最终发现的问题。

在我的浏览器应用程序中,我在特定位置绘制了多个不同大小的圆圈,然后拖动整个屏幕的可见部分,仅显示在当前缩放级别可见的完整背景中的圆圈。 拖动鼠标会生成一个mousemove事件,该事件会触发对我的渲染例程的调用,这会对每个可见的圆圈进行重新绘制。

在IE 11中进行测试时,我发现一旦我在可视区域中有大约100个圆圈,拖动鼠标时渲染变得非常不稳定。 分析器表明这几乎完全是由paint()例程引起的。

我的代码已经使用了库中的requestAnimationFrame()。 有趣的是,在拖动屏幕时,我看到了减速; 但如果我只是拖动屏幕并释放它,让图书馆代码继续以减速为动画制作动画,重新绘制就像黄油一样平滑。 仅在拖动鼠标时才会发生减速。 这个问题肯定与mousemove有关。 (稍等一下。)

我把paint()例程简化为一个简单的填充弧 – 同样的问题。 每当我更改缩放级别时,我都尝试将填充的圆圈绘制到离屏canvas上,然后使用drawImage()将屏幕外canvas复制到我的主屏幕 – 这提高了性能,但它在IE中仍然不稳定。 然后我尝试使用这种技术将所有圆圈绘制到与我的主要可见窗口大小相同的屏幕外canvas,然后更改paint()除了将屏幕外canvas复制到我的可见canvas之外什么也没做 – 这再次给出了一点改进,但还不够。

然后我尝试在各种浏览器中运行我的应用:

IE 11:非常不稳定的Firefox 42:非常波动的Chrome 47:在所有缩放级别都非常流畅Opera 34:在所有缩放级别都非常流畅桌面Safari 5.1.7(在PC上):在所有缩放级别上略微不稳定

这个问题肯定与mousemove以及它是如何由不同的浏览器处理有关。

最终我在StackOverflow上发现了这个问题,并且它建议鼠标本身发送了如此多的mousemove事件,以至于它正在淹没浏览器快速重绘的能力。 我确实有一个具有高事件发生率的现代鼠标。

我尝试将eventThrottle检查添加到我的mousemove事件处理程序中,瞧! 成功。 我的代码现在可以在所有浏览器上顺利呈现。 (高兴地投票。:))

我想为那些在使用高频鼠标拖动时可能遇到IE和Firefox中糟糕的paint()性能问题的人添加这些附加信息。 建议的节流鼠标移动事件的解决方案对我有用。

1 – 有一个油门jQuery插件: https : //github.com/cowboy/jquery-throttle-debounce

正如您可以在示例中看到的那样 ,您可以替换:

 // Bind the not-at-all throttled handler to the resize event. $(window).resize( handler ); // Bind the throttled handler to the resize event. $(window).resize( $.throttle( 250, handler ) ); // This is the line you want! 

2 – 你想发布你的处理程序的代码吗?

一个盲目的建议:Firebug在FF 24中存在性能问题。您是否尝试将性能与Firebug启用/禁用进行比较?