Estoy desarrollando un motor de juego en HTML5. Los personajes son elementos div que usan un sprite animado como fondo. Como la animación de sprites tiene parámetros fluidos y debe configurarse mediante código, no se pueden predefinir en una definición de CSS estática, por lo tanto, uso element.animate para configurar animaciones de sprites en una fila dada a una velocidad determinada conociendo mis escalas y recuentos de fotogramas.
// Applies the given frame and animation to the sprite // Frame is an angle, clockwise direction: 0 = up, 1 = right, 2 = down, 3 = left set_animation(frame, duration) { const scale_x = this.settings.sprite.scale_x * this.settings.sprite.frames_x; const pos_y = this.settings.sprite.scale_y * -frame; // Cancel the existing animation if(this.data_actors_self.anim) { this.data_actors_self.anim.cancel(); this.data_actors_self.anim = null; } // Play the animation for this row or show the first frame if static if(duration > 0) { this.data_actors_self.anim = this.element.animate([ { backgroundPosition: px([0, pos_y]) }, { backgroundPosition: px([scale_x, pos_y]) } ], { duration: duration * 1000, direction: "normal", easing: "steps(" + this.settings.sprite.frames_x + ")", iterations: Infinity }); this.data_actors_self.anim.play(); } else { this.element.style.backgroundPosition = px([0, pos_y]); } } Obviamente, ese es un fragmento de una función de clase de actor: this.element es el div, this.settings es un objeto con parámetros para usar cuyos nombres deberían tener sentido en este contexto, la función px() es un convertidor simple para convertir matrices en cadenas de píxeles para HTML (p. ej.: [0, 0] a "0px 0px" ).
El problema que tengo: si bien siempre puedo ejecutar esta función para establecer una nueva animación, quiero poder cambiar la velocidad de la animación sin restablecerla. No es necesario que sea una transición suave, por lo que a mí respecta, la nueva velocidad se puede aplicar en la siguiente iteración... Solo quiero evitar un chasquido visual o cualquier tipo de reinicio al aplicar el cambio. Una vez que se configura una animación, no tengo idea de cómo acceder y actualizar su parámetro de duration . ¿Alguien tiene alguna sugerencia?
Cuando uso console.log en this.data.anim , me dicen con razón que es un objeto de animación. Intenté usar JSON.stringify para obtener más información, pero no se imprime nada relevante. this.data.anim.duration devuelve undefined , por lo que la configuración debe almacenarse en alguna otra propiedad. Incluso si conozco esa propiedad, me gustaría estar seguro de que los navegadores web estarán de acuerdo conmigo en cambiarla this.data.anim.options.duration = new_duration .
Puede esperar al final de una iteración antes de cambiar la duración de la animación si eso es lo que se requiere.
Este fragmento solo establece un detector de eventos para el evento de iteración de animación cuando hace clic en el botón para aumentar la velocidad.
function upthespeed() { const div = document.querySelector('div'); div.addEventListener('animationiteration', function() { div.style.animationDuration = '1s'; }); document.querySelector('button').style.display = 'none'; } div { width: 10vmin; height: 10vmin; background-color: magenta; animation: move 10s linear infinite; } @keyframes move { 0% { transform: translateX(50vw); } 50% { transform: translateX(0); } 100% { transform: translateX(50vw); } } <div></div> <button onclick="upthespeed()">Click me to increase the speed at the end of the next iteration (you may have to wait!)</button>El valor de la duración de la animación no está en el objeto Animation en sí, sino en la propiedad animation-duration CSS para el elemento: por lo tanto, this.data_actors_self.style.animationDuration = new_duration hará el trabajo. Sin embargo, reiniciará la animación si se está reproduciendo, pero si entiendo correctamente, eso no es un problema para usted.
Editar : para cambiar la duración de la animación sin reiniciarla, todo lo que tiene que hacer es establecer el valor de anim.startTime a lo que era antes. Por ejemplo:
const startTime = anim.startTime; this.data_actors_self.style.animationDuration = new_duration anim.startTime = startTime;