Estoy tratando de animar un div al presionar la keypress de la barra espaciadora que funciona perfectamente bien, pero al presionar la barra espaciadora varias veces, los eventos se suman en DOM y se ejecutan uno tras otro.
Intenté dejar de grabar los activadores recientes hasta que se ejecuta el actual, pero fallé.
Este es el código:
$('body').keypress(function(e){ if(e.keyCode == 32){ $(".character").animate({top: '-=300px'}, 500); $(".character").animate({top: '+=300px'}, 500); } } });El código que probé agregando una clase y eliminándola para diferenciarla:
$('body').keypress(function(e){ if(e.keyCode == 32){ if($(".character").hasClass("character_jumping")) { } else { $(".character").addClass("character_jumping"); $(".character_jumping").animate({top: '-=300px'}, 500); $(".character_jumping").animate({top: '+=300px'}, 500); $(".character").removeClass("character_jumping"); } } }); El código que probé con event.stopPropagation(); :
$('body').keypress(function(e){ if(e.keyCode == 32){ $(".character").animate({top: '-=300px'}, 500); $(".character").animate({top: '+=300px'}, 500); } } event.stopPropagation(); });Ninguno funcionó como esperaba. Todo lo que estoy tratando de obtener es decirle a DOM que no registre ninguna tecla de la barra espaciadora hasta que finalice la animación del personaje.
stopPropagation no funcionó porque todo lo que hace es evitar que el evento se propague a los elementos del contenedor, no evita que llegue al controlador al que ya llamó el evento.
Su solución de clase funcionaría, pero está eliminando la clase demasiado pronto. Debe esperar a que finalice la animación, utilizando la devolución de llamada de fin de animación ( docs ):
$('body').keypress(function(e){ if(e.keyCode == 32){ if ($(".character").hasClass("character_jumping")) { } else { $(".character").addClass("character_jumping"); $(".character_jumping").animate({top: '-=300px'}, 500); $(".character_jumping").animate({top: '+=300px'}, 500, () => { // *** $(".character").removeClass("character_jumping"); // *** }); // *** } } }); Otra opción es finalizar prematuramente la animación con stop y comenzar de nuevo al presionar una tecla.
Nota al margen: es una cuestión de estilo, pero sugeriría usar ! en lugar de un bloque if vacío. El bloque if vacío es muy inusual y, por lo tanto, se pierde fácilmente:
$('body').keypress(function(e){ if(e.keyCode == 32){ if (!$(".character").hasClass("character_jumping")) { // *** // ^ *** $(".character").addClass("character_jumping"); $(".character_jumping").animate({top: '-=300px'}, 500); $(".character_jumping").animate({top: '+=300px'}, 500, () => { $(".character").removeClass("character_jumping"); }); } } });