1

In Javascript, is it possible in a mousemove event handler to determine if there are any pending mousemove events in the queue?

Or, preferably, is it possible to make the event queue skip all mousemove events in the queue except for the most recent one?

I'm using mousemove & other mouse events to allow users to drag elements around the screen, and I don't need to waste CPU & GPU cycles redrawing the dragged items on every mousemove event (in which I update the top & left CSS properties), as long as I can skip intermediate events quickly enough.

My site is not currently experiencing any performance or visualization problems; I just want to make my JavaScript as efficient as possible.

XDR
  • 4,070
  • 3
  • 30
  • 54
  • Define "redrawing". Is it just setting `left`/`top` properties, or is it more involved? – Crescent Fresh Feb 19 '13 at 00:18
  • I think there are more interesting ways to fix your problem than checking the event queue. That sort of code is really hard to get right. It's easier to just set a timer and only redraw if, say, 1/10th second has gone by. Make the time longer if you need to reduce the load on the hardware but they say people can detect events down to 1/10 sec apart. So redrawing more often is doing something that most people can't even detect (though, it is possible that a flickering effect seems detectable to some people). – Lee Meador Feb 19 '13 at 00:21
  • @CrescentFresh: Yes, redrawing is just `left`/`top` properties. – XDR Feb 19 '13 at 02:46
  • The 1/10 of a second estimate depends on what you are doing. Human motions that take 1/10 of a second, say in athletics, are visible to a person and are noticeable when missing. A 1/10 second drag behind a moving mouse will be quite noticeable I think. Human speech involves all sorts of bits that are less than 1/10 of a second and that stand out when omitted. –  Jul 17 '15 at 20:31

2 Answers2

1

Use event debouncing. This small throttle/debounce library works well with or without jQuery.

Example:

function someCallback() {
    // snip
}

// don't fire more than 10 times per second
var debouncedCallback = Cowboy.debounce(100, someCallback);
document.getElementById('some-id').addEventListener('mousemove', debouncedCallback);
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
0

You could keep track of the last time you handled a mousemove, then skip the current one if it's too soon.

For example:

elem.onmousemove = function() {
    var lastcalled = arguments.callee.lastCallTime || 0,
        now = new Date().getTime();
    if( now-lastcalled < 250) return;
    arguments.callee.lastCallTime = now;
    // rest of code here
};
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592