2011-01-10 6 views
7

Estoy tratando de encontrar una forma limpia de agregar eventos de mousemove para asegurarme de que se llame a mi código, pero solo una vez cada 250-300 milisegundos.jQuery: Firemove los eventos de mouse menos a menudo

He pensado en usar algo como lo siguiente, pero me preguntaba si había un patrón mejor, o algo jQuery dispone que va a hacer lo mismo:

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: La respuesta aceptada a continuación funcionaría perfectamente para esta situación, sin embargo, encontré que la funcionalidad mousestop() incluida en la respuesta eliminó realmente mi necesidad de agregación, por lo que si está leyendo esta pregunta y buscando una respuesta, vea si el complemento mousestop es lo que ¡realmente necesito!

Respuesta

5

Su código está bien, excepto que usted debe clear the timeout antes de colocarlo en nulo o puede filtrarse:

window.clearTimeout(mousemove_timeout); 
mousemove_timeout = null; 

Como alternativa, se podría utilizar mousemove/mousestop conjuntamente con 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; 
}); 
+0

+1 - ¡Gracias por la sugerencia! ¿Es esta la mejor/más limpia? Parece un truco de hack ... –

+1

Sí, de hecho es un poco hackeo, 'window.setInterval' sería más adecuado para este escenario. –

+0

¡Aceptado! - Resulta que la función 'mousestop' es exactamente lo que necesito y eliminará completamente el código de tiempo de espera. ¡Muchas gracias! –

4

Una solución y una pregunta ^^

¿Qué pasa con este enfoque sin una var global. ¿Es esa una solución adecuada?

$(function() { 
    $("#foo").mousemove((function() { 
     var timer = null; 

     return function() { 
      if (timer !== null) { 
       window.clearTimeout(timer); 
      } 
      timer = window.setTimeout(foo, 250); 
     }; 
    })()); 
}); 

function foo() { 
    //... 
} 
+1

+1 - Definitivamente me gusta no usar una variable global. Aunque no he probado este código, parece bastante limpio e intuitivo. –

+0

+1 Mejor solución – algorhythm

1

Esta fue una pregunta realmente interesante. He encontrado una manera menos hacker para hacer esto, y usted puede comprobar fuera de este live demo del siguiente fragmento:

({ 
    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(); 
16

Después de probar la solución en la respuesta aceptada, descubrí que si el ratón mantenerse en movimiento constante , especialmente en movimiento circular, el evento mousemove() se dispara continuamente, pero las coordenadas del mouse permanecen iguales. Así que se me ocurrió una solución más simple que elimina mousestop() y setTimeout.

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

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

Esto llamará correctamente a handleMouseMove() aproximadamente cada 100 ms. (Tenga en cuenta que he dicho aproximadamente porque los retrasos de tiempo e intervalos de JavaScript no es en tiempo real garantizado)

+1

+1 - ¡Gracias! Este es realmente el tipo de solución que estaba buscando originalmente. Este es un enfoque mucho más limpio que la respuesta aceptada, pero el plugin mousestop sigue siendo lo que yo elegí. –

+0

¿Hay alguna manera de detener el temporizador cuando el mouse no se mueve? – interstellarDust

1

Puede guardar algunas líneas utilizando el tiempo de espera para anular el temporizador:

var paused = null; 

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

Una forma simple de Alcanzar la posición del mouse en un período personalizado de milisegundos

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

Busca el código de limitación/eliminación de rebotes.

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

de ejemplo de subrayado.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); 
    }; 
}; 
1

Yo sé que soy un poco tarde a la fiesta, pero podría ser de utilidad para las personas que visitan este hilo, aquí es mi 2 centavos.

Utilizando el operador de módulo y los incrementos numéricos simples, puede reducir la velocidad de disparo de su función con un golpe de rendimiento mínimo, como tal;

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

Además, si usted tiene miedo de golpear el límite máximo número entero, puede restablecer la variable X disparado cada mil visitas (de nuevo, usando el operador de módulo) o utilizando el evento mouseout.

Cuestiones relacionadas