@keyframes y JavaScript

facebook-svg gplus-svg twitter-svg

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