Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: Fire mousemove events less often

I'm trying to figure out a clean way to aggregate mousemove events so that I ensure my code gets called, but only once every 250-300 milliseconds.

I've thought about using something like the following, but was wondering if there was a better pattern, or something jQuery provides that will do the same thing:

var mousemove_timeout = null;

$('body').mousemove(function() {
  if (mousemove_timeout == null) {
    mousemove_timeout = window.setTimeout(myFunction, 250);
  }
});

function myFunction() {
  /*
   * Run my code...
   */

  mousemove_timeout = null;
}

EDIT: The accepted answer below would work perfectly for this situation, however, I found that the mousestop() functionality provided in the answer actually eliminated my need for the aggregation, so if you're reading this question and looking for an answer, see if the mousestop plugin is what you really need!

like image 252
Topher Fangio Avatar asked Jan 10 '11 15:01

Topher Fangio


2 Answers

After I tried the solution in the accepted answer, I found out that if the mouse keep moving constantly, especially in circular motion, mousemove() event is fired continuously, but the mouse coordinates remain the same. So I came up with a simpler solution which eliminates mousestop() and setTimeout.

$("body").mousemove(function (e) {
        if (enableHandler) {
            handleMouseMove(e);
            enableHandler = false;
        }
});

timer = window.setInterval(function(){
    enableHandler = true;
}, 100);

This will correctly call handleMouseMove() approximately every 100ms. (Note that I said approximately because time delays and intervals in JavaScript is not real-time guaranteed)

like image 95
Ethan Avatar answered Oct 02 '22 14:10

Ethan


Your code is fine except that you should clear the timeout before setting it to null or it might leak:

window.clearTimeout(mousemove_timeout);
mousemove_timeout = null;

As an alternative you could use mousemove/mousestop in conjunction with window.setInterval

var timer = null;
var isIntervalSet = false;

$('body').mousemove(function() {
    if (isIntervalSet) {
        return;
    }
    timer = window.setInterval(function() {
        /*
        * Run my code...
        */    
    }, 250);
    isIntervalSet = true;
}).mousestop(function() {
    isIntervalSet = false;
    window.clearTimeout(timer);
    timer = null;
});
like image 34
Darin Dimitrov Avatar answered Oct 02 '22 14:10

Darin Dimitrov