6

I have an event handler bound to the mousemove handler which will log the current mouse position via console.log().I am aiming to have the event fire no more than 5 times a second so as to prevent being overwhelmed whenever i move my mouse.

Currently, i have the code below, which is logging the mouse position everytime it moves, BUT is not throttling it and i can't seem to figure out what's going wrong

//Code runs after document is ready

function logMouse(event){
    console.log('The mouse is currently at ('+event.pageX+','+event.pageY+')');
  }
  $(document).on('mousemove',function(event){
    setTimeout(function(){
      logMouse(event);
    },200);
  });  

I am trying to throttle the mousemove events by using setTimeout, and setting the timer to 200 mse so that it would fire 5 times in 1 second, but my code isn't working and is currently just giving me a mass of mouse positions whenever i move my mouse.

How do i throttle my mousemove so that it performs the logging of the mouse's position no more than 5 times a second?

Kenneth .J
  • 1,433
  • 8
  • 27
  • 49

2 Answers2

10

Add a variable that tracks when an event has just occurred, and sleep with setTimeout before allowing the next event.

var timesPerSecond = 5; // how many times to fire the event per second
var wait = false;
$(document).on('mousemove', function (event) {
    // don't handle events when one has just occurred
    if (!wait) {
        // fire the event
        logMouse(event);
        // stop any further events
        wait = true;
        // after a fraction of a second, allow events again
        setTimeout(function () {
            wait = false;
        }, 1000 / timesPerSecond);
    } 
});

Alternatively, you can avoid the setTimeout and just track the latest time when an event has occurred.

var timesPerSecond = 5; // how many times to fire the event per second
var waitUntil = 0;
$(document).on('mousemove', function (event) {
    // don't handle events when one has just occurred
    if (Date.now() >= waitUntil) {
        // fire the event
        logMouse(event);
        // stop any further events for a moment
        waitUntil = Date.now() + 1000 / timesPerSecond;
    } 
});
PurkkaKoodari
  • 6,703
  • 6
  • 37
  • 58
1

I use this wrapper function throughout my projects. Unfortunately at the time of writing I didn't know about the proper terminology throttling.

// ignore fast events, good for capturing double click
// @param (callback): function to be run when done
// @param (delay): integer in milliseconds
// @param (id): string value of a unique event id
// @doc (event.timeStamp): http://api.jquery.com/event.timeStamp/
// @bug (event.currentTime): https://bugzilla.mozilla.org/show_bug.cgi?id=238041
ignoredEvent: (function () {
    var last = {},
        diff, time;

    return function (callback, delay, id) {
        time = (new Date).getTime();
        id = id || 'ignored event';
        diff = last[id] ? time - last[id] : time;

        if (diff > delay) {
            last[id] = time;
            callback();
        }
    };
})(),

You can use it like this:

$(document).on('mousemove',function(event){
    ignoredEvent(function(){
        logMouse(event);
    }, 200, 'mouse-move');
});
Tim Vermaelen
  • 6,869
  • 1
  • 25
  • 39