@keyframes y JavaScript
Las animaciones CSS3 son muy versátiles, y tienen un mejor rendimiento comparadas con las animaciones JavaScript. Pero a veces necesitamos tener más control sobre la animación, y para esto además del CSS necesitamos utilizar JavaScript.
En JavaScript existen 3 tipos de eventos que "saltan" durante las animaciónes:
- uno que se dispara al iniciarse la animación ( animationstart
o webkitAnimationStart
)
- otro que salta con cada iteración ( animationiteration
o webkitAnimationIteration
), y finalmente
- otro evento que se dispara al final. ( animationend
o webkitAnimationEnd
)
animationstart
Este evento salta cuando la animación empieza por la primera vez.
El nombre del controlador del evento ( event handler ) es animationstart
pero en navegadores de tipo webkit tenemos que utilizar webkitAnimationStart
.
Para utilizar este evento, empezamos guardando en una variable el elemento al que queremos animar:
var animacion = document.getElementById("animacion");
Después aplicamos el método addEventListener
de esta manera:
animacion.addEventListener("webkitAnimationStart ", alEmpezarLaAnimacion, false); animacion.addEventListener("animationstart", alEmpezarLaAnimacion, false);
La función alEmpezarLaAnimacion
es un receptor de eventos ( event listener ), o sea una función personalizada ( custom function ) que toma como atributo el evento ( e
), y que, naturalmente tenemos que escribir.
Para mantener las cosas muy sencillas, solo para ver como funciona esto, escribimos esta función:
function alEmpezarLaAnimacion(e){ animacion.style.backgroundColor = "#f00"; console.log("La animaci\363n "+ e.animationName+" acaba de empezar"); }
Donde e
es el evento, animationstart
en este caso. Observe por favor que para escribir la ó de "animación" utilizamos el código hexadecimal de este, precedido por el carácter de escape ( \ ) así: \363
.
Lea más acerca de Símbolos ASCII y Unicode, y cómo utilizarlos en JavaScript.
Los eventos son objetos que tienen métodos y propiedades, como por ejemplo animationName
que ya hemos visto arriba. Para ver todos los métodos y propiedades de un evento podemos sacarlos en consola así:
function alEmpezarLaAnimacion(e){ animacion.style.backgroundColor = "#f00"; console.log( e ); }
Lea más acerca del método addEventListener
animationiteration
Este evento se dispara con cada iteración, justo en el momento en el cual la animación empieza de nuevo. Si por ejemplo la animación se repite 3 veces este evento salta dos veces, al principio de la segunda y la tercera repetición.
El nombre del controlador del evento ( event handler ) es animationiteration
pero en navegadores de tipo webkit utilizamos webkitAnimationIteration
.
animacion.addEventListener("webkitAnimationIteration", alRepetirLaAnimacion, false); animacion.addEventListener("animationiteration", alRepetirLaAnimacion, false);
En este caso la función alRepetirLaAnimacion
es el receptor de eventos ( event handler ).
animationend
Este evento salta al acabarse la animación y puede ser muy útil si queremos ejecutar la animación más de una vez.
El nombre del controlador del evento ( event handler ) es animationend
pero en navegadores de tipo webkit utilizamos webkitAnimationEnd
.
animacion.addEventListener("webkitAnimationEnd", alAcabarLaAnimacion, false); animacion.addEventListener("animationend ", alAcabarLaAnimacion, false);
Donde la función alAcabarLaAnimacion
es el receptor de eventos ( event handler ).
Un caso práctico
En el HTML tenemos un corazón SVG. El trazado <path>
que dibuja el corazón tiene asignado el id="corazon"
. Al hacer clic en este trazado la animación latido
empieza y los eventos de la animación aparecen documentados en <pre id="consola">
.
En el CSS, la animación latido
es muy sencilla: solo tres fotogramas.
@keyframes latido { 0% { -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1); } 70% { -webkit-transform: scale(1.3); -ms-transform: scale(1.3); transform: scale(1.3); } 100% { -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1); } }
La animación latido
dura 0.6 segundos y se repite 6 veces.
#corazon.latido{ animation : latido .6s linear 6 alternate; }
Es importante observar que además del id #corazon
aparece la clase .latido
.
En el JavaScript empezamos definiendo dos variables: el corazon
y la consola
.
var corazon = document.querySelector("#corazon"); var consola = document.querySelector("#consola");
Al hacer clic en el #corazon
queremos que empiece la animación. Para esto utilizamos el método setAttribute
para dar al corazón la clase .latido
.
corazon.addEventListener("click", function(){ corazon.setAttribute("class","latido"); });
Ahora viene la parte importante: aprovechar los eventos que pasan durante la animación.
// Para navegadores -webkit- corazon.addEventListener("webkitAnimationStart", alEmpezarLaAnimacion, false); corazon.addEventListener("webkitAnimationIteration", alRepetirLaAnimacion, false); corazon.addEventListener("webkitAnimationEnd", alAcabarLaAnimacion); // La sintaxis estandar corazon.addEventListener("animationstart", alEmpezarLaAnimacion, false); corazon.addEventListener("animationiteration", alRepetirLaAnimacion, false); corazon.addEventListener("animationend", alAcabarLaAnimacion, false);
Y escribir las funciones que controlan lo que pasa al empezar, al repetir y al acabar la animación.
function alEmpezarLaAnimacion(e) { consola.textContent = "La animaci\363n \""+ e.animationName+"\" acaba de empezar.\n"; } function alRepetirLaAnimacion(e) { consola.textContent += "La animaci\363n \""+ e.animationName+"\" vuelve a repetirse. Han pasado "+ Number((e.elapsedTime).toFixed(1)) +" segundos.\n"; } function alAcabarLaAnimacion(e) { this.removeAttribute("class"); consola.textContent += "La animaci\363n \""+ e.animationName+"\" se ha acabado. Han pasado "+ Number((e.elapsedTime).toFixed(1)) +" segundos."; }
Al acabarse la animación quitamos la clase ".latido
". De esta manera la próxima vez que hagamos clic en el #corazon
, la animación volverá a empezar.
#corazon {fill:#ED1F24;}
#corazon.latido {
fill="#ED1F24";
-webkit-animation: latido .6s linear 6 alternate;
animation: latido .6s linear 6 alternate;
}
svg{ border:none;}
#consola{ width:90%; margin:0 auto;}
var corazon = document.querySelector("#corazon");
var consola = document.querySelector("#consola");
corazon.addEventListener("click", function(){
corazon.setAttribute("class","latido");
});
// Para navegadores -webkit-
corazon.addEventListener("webkitAnimationStart", alEmpezarLaAnimacion, false);
corazon.addEventListener("webkitAnimationIteration", alRepetirLaAnimacion, false);
corazon.addEventListener("webkitAnimationEnd", alAcabarLaAnimacion);
// La sintaxis estandar
corazon.addEventListener("animationstart", alEmpezarLaAnimacion, false);
corazon.addEventListener("animationiteration", alRepetirLaAnimacion, false);
corazon.addEventListener("animationend", alAcabarLaAnimacion, false);
function alEmpezarLaAnimacion(e) {
consola.textContent = "La animaci\363n \""+ e.animationName+"\" acaba de empezar.\n";
}
function alRepetirLaAnimacion(e) {
consola.textContent += "La animaci\363n \""+ e.animationName+"\" vuelve a repetirse. Han pasado "+ Number((e.elapsedTime).toFixed(1)) +" segundos.\n";
}
function alAcabarLaAnimacion(e) {
this.removeAttribute("class")
consola.textContent += "La animaci\363n \""+ e.animationName+"\" se ha acabado. Han pasado "+ Number((e.elapsedTime).toFixed(1)) +" segundos.";
}
Vea una demostración