jQuery mousemove表现 - 油门事件? [英] jQuery mousemove performance - throttle events?

查看:148
本文介绍了jQuery mousemove表现 - 油门事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我们有一个屏幕填充画布,需要跟踪用户是否拖动鼠标,所以我们在这个对象上添加了一个鼠标移动监听器:

  ourCanvas.on('mousemove',
函数(事件){
event.preventDefault();
//我们的拖动代码在这里
}
});

此代码工作正常,但是我们在当前的Firefox(24)中出现了严重的性能问题系统。 profiler告诉我们,大部分时间都花在了 jQuery.event.dispatch()(我们尝试了当前最新的jQuery 1.8,1.9,1.10和2.0)。 p>

我们通过使用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(现在> lastMove + eventThrottle){
lastMove = now;
//我们的拖动代码在这里
}
}
});

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



现在我有两个问题:


  1. 我们还有其他位置,我们将mousemove监听器附加到不同的HTML元素,我想将所有这些手动节气门添加到所有这些 mousemove 处理程序不再遇到问题。这是否可以在jQuery(2.0.3)中以很好的方式做?我在jQuery javascript中看到了 preDispatch 钩子,但是它们已经在调用fix()之后,也使用了一些时间,我也想保存该调用


  2. 我感到困惑的是,已经有一个2ms的ms code> eventThrottle 已经足够了,表现,所以我添加了一个计数器,看看有多少事件被跳过。令人惊讶的结果:它仅跳过0-1事件...在100ms的节气门处,跳过的事件大约为60-70,所以如果每ms少于1个mousemove事件,为什么这样代码具有如此积极的效果?


感谢任何评论,
Christopher

解决方案

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



在我的浏览器应用程序中,我在特定位置上绘制各种尺寸的多个圆圈,然后拖动整个屏幕的可见部分,仅显示在当前缩放级别可见的完整背景中的圆形。拖动鼠标会生成一个mousemove事件,它触发对我的渲染例程的调用,这反过来会导致每个可见圆的重绘。



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



我的代码已经在库中使用requestAnimationFrame()。有趣的是,在拖动屏幕的同时,我看到了放缓;但是如果我只拖曳屏幕并释放它,让图书馆代码继续以减速动画动画,重画就像黄油一样流畅。只有拖动鼠标时才发生减速。这个问题绝对似乎是与mousemove。 (回到这一刻。)



我把paint()程序减少到一个简单的填充弧 - 同样的问题。当我改变缩放级别时,我尝试将填充的圆圈画成一个离线画布,然后使用drawImage()将屏幕外画布复制到我的主屏幕 - 这种改进的性能,但在IE中仍然不可用。然后,我尝试使用这种技术将所有圈子画成与我的主要可见窗口相同的屏幕画布,然后更改paint(),除了将屏幕外画布复制到可见的画布之外,这再次给出了一个小的改进,但不够。



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



IE 11:非常波动
Firefox 42:非常波折
Chrome 47:在所有缩放级别上完美平滑
Opera 34:在所有缩放级别完美平滑
桌面Safari 5.1.7(在PC上):略有波动在所有缩放级别



问题绝对与mousemove相关,以及不同浏览器的处理方式。



最终,我在StackOverflow上发现了这个问题,并建议鼠标本身会发送如此多的mousemove事件,这样才能使浏览器的速度足够快。我有一个现代的老鼠,具有很高的事件发生率。



我尝试将eventThrottle检查添加到我的mousemove事件处理程序,并瞧瞧!成功。我的代码现在在所有浏览器上顺利呈现。 (upvoted with pleasure。:))



我想为任何可能遇到IE和Firefox的paint()性能问题拖拽的人添加这些附加信息用高频鼠标。提出的节流mousemove事件的解决方案对我有用。


We are facing a problem with jQuery event propagation performance connected to mousemove:

We have a screen filling canvas and need to track if a user drags the mouse on it, so we have added a mouse move listener on that object like this:

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

This code works fine, but we had severe performance issues in the current Firefox (24) on one test system. The profiler tells us, that most of the time was spent in jQuery.event.dispatch() (we tried current latest jQuery 1.8, 1.9, 1.10 and 2.0).

We successfully decreased the time spent in the dispatch() function by using the "jQuery.event.fix()" performance optimization here: http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html but performance on that test system was still way below what we expected.

After some further testing, I managed to pin this down on the mouse used on the system: It used 1000Hz. We switched the used mouse down to 125Hz and voila, the performance was great.

Our assumption was, that the high Hz rate on the mouse caused a lot of mousemove events, so we changed the above code to apply an event throttle and only call the event handling every X milliseconds:

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
      }
   }
});

And it worked like a charme, the performance was great. Even though we only skip two milliseconds of events.

Now I have two questions:

  1. We have other locations where we attach mousemove listeners to different HTML elements and I'd like to add this hand-made throttle to all of those mousemove handlers to not run into the problem again. Is this somehow possible to do in a nice way in jQuery (2.0.3)? I've seen preDispatch hooks in the jQuery javascript but they are already after the call to fix() which also uses some time and I'd like to save that call as well.

  2. I was puzzled by the fact that already an eventThrottle of 2ms was sufficient to get really good performance so I added a counter to see how many events are being skipped. The surprising result: it skips only 0-1 events... With a throttle of 100ms, the skipped events were in the order of 60-70, so if there is less than 1 mousemove event per ms, why does this code have such a positive effect after all?

Thanks for any comments, Christopher

解决方案

In late 2015 I ran into what I eventually discovered was this problem.

In my browser app I paint multiple circles of various sizes at particular locations, then I drag the visible portion of the total screen, revealing only the circles from the full background that are visible at the current zoom level. Dragging the mouse generates a mousemove event, which triggers a call to my render routine, which in turn causes a repaint for each visible circle.

In testing this in IE 11, I found that once I had around 100+ circles in the viewable area, rendering while dragging the mouse became extremely choppy. The profiler indicated this was almost entirely due to the paint() routine.

My code was already using requestAnimationFrame() from a library. Interestingly, while dragging the screen, I saw the slowdown; but if I only dragged the screen and released it, letting the library code continue to animate the movement with deceleration, repainting was smooth as butter. The slowdown occurred only while dragging the mouse. The problem definitely seemed to be with mousemove. (Back to this in a moment.)

I pared down the paint() routine to nothing but a simple filled arc -- same problem. I tried painting the filled circle to an off-screen canvas whenever I changed the zoom level, then using drawImage() to copy the offscreen canvas to my main screen -- this improved performance, but it was still unusably choppy in IE. I then tried using this technique to paint all the circles to an offscreen canvas the same size as my main visible window, then changing paint() to do nothing but copy the offscreen canvas to my visible canvas -- this again gave a small improvement, but not enough.

I then tried running my app in various browsers:

IE 11: very choppy Firefox 42: very choppy Chrome 47: perfectly smooth at all zoom levels Opera 34: perfectly smooth at all zoom levels Desktop Safari 5.1.7 (on PC): slightly choppy at all zoom levels

The problem was definitely related to mousemove and to how it's handled by different browsers.

Eventually I found this question on StackOverflow and its suggestion that the mouse itself is sending so many mousemove events that it's swamping the ability of the browser to repaint quickly enough. And I do have a modern mouse with a high event generation rate.

I tried adding the eventThrottle check to my mousemove event handler, and voila! Success. My code now renders smoothly on all browsers. (Upvoted with pleasure. :) )

I wanted to add this additional information for anyone who might be encountering the problem of poor paint() performance in IE and Firefox while dragging with a high-frequency mouse. The proposed solution to throttle mousemove events worked for me.

这篇关于jQuery mousemove表现 - 油门事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆