JQuery: Places for Fire Mousemove Less

I am trying to find a clean way to aggregate mousemove events, so that I ensure that my code is called, but only once every 250-300 milliseconds.

I thought about using something like the following, but wondered if there was a better pattern, or something that provides jQuery that would do the same:

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 answer below will work fine for this situation, however, I found that the mousestop() functionality provided in the answer actually eliminated my aggregation need, so if you read this question and look for the answer, see if mousestop is really needed plugin

+7
source share
9 answers

Your code is fine, except that you must clear the timeout before setting it to null or it may leak:

 window.clearTimeout(mousemove_timeout); mousemove_timeout = null; 

Alternatively, you can use mousemove / mousestop in combination 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; }); 
+5
source

After I tried the solution in the accepted answer, I found out that if the mouse is constantly moving, especially in a circular motion, the mousemove () event is fired continuously, but the coordinates of the mouse remain unchanged. So I came up with a simpler solution that 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 100 ms. (Note that I said roughly because time delays and intervals in JavaScript are not guaranteed in real time)

+16
source

Solution and Question ^^

How about this approach without a global var. Is this a suitable solution?

 $(function() { $("#foo").mousemove((function() { var timer = null; return function() { if (timer !== null) { window.clearTimeout(timer); } timer = window.setTimeout(foo, 250); }; })()); }); function foo() { //... } 
+4
source

An easy way to get the user’s mouse position in milliseconds

 var timer; var refresh_time = 50; var x = 0; jQuery('body').mousemove(function(evt) { if (timer) clearTimeout(timer); timer = setTimeout(function(){ var mouse_x = evt.clientX; if(mouse_x != x){ x = mouse_x; console.log('mouse is on a new x position' + x); } }, refresh_time); }) 
+3
source

You are requesting a Throttling / Debouncing code.

http://benalman.com/projects/jquery-throttle-debounce-plugin/ http://drupalmotion.com/article/debounce-and-throttle-visual-explanation

Sample from underscore.jS

 // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; 
+2
source

That was a really interesting question. I found a less hacky way to do this, and you can check out this live demo of the following snippet:

 ({ event: null, interval: null, init: function(){ var self = this; $(document).bind("mousemove", function(e){self.event=e;}); this.interval = setInterval(function(){ /** do what you wish **/ console.log(self.event); }, 250); return this; }, stop: function(){ $(document).unbind("mousemove", this.event); clearInterval(this.interval); }, }).init(); 
+1
source

You can save multiple lines using a timeout for a null timer:

 var paused = null; $("body").mousemove(function (e) { if (!paused){ /** your code here **/ paused = setTimeout(function(){paused=null}, 250); } }); 
+1
source

I know that I'm a little late for the party, but it can be useful for people visiting this topic, here are my 2 cents.

Using the module operator and simple increments of the number, you can reduce the rate of fire of your function with minimal impact on performance;

 var fired = 0; $('#element').on('mousemove', function(){ fired++; // Fire 5x less than usual if(!(fired % 5) || fired == 1) yourFunction(); }) 

In addition, if you are afraid of falling into the maximum integer limit, you can reset the fired variable every X thousand strokes (again, using the module operator) or with the mouseout event.

+1
source

Why not use setInterval () instead of timeouts?

0
source

All Articles