Cómo animar un gráfico en SVG

20/02/2017
Cómo animar un gráfico en SVG

En el post, vamos a hablar sobre las animaciones con CSS, en principio sin el uso de ninguna librería javascript. Para ello, tomaremos como ejemplo una animación que hemos creado para nuestra nueva  página web, que estará disponible en breve.

Comenzaremos indicando que lo más importante de una animación es el diseño en formato SVG, es decir, el diseño debe ser un conjunto de vectores, que como ya sabréis, nos permiten cambiar el tamaño de las animación sin perder nada de calidad. En este post no vamos a abordar cómo se realiza, sólo indicaremos que se crea con algún programa vectorial (illustrator, Inkscape...)

Una vez que tenemos el archivo, en nuestro caso community.svg, lo abriremos con un programa de código (sublime text, notepad++,...). Este diseño nos indicará la posición de cada uno de los elementos en el momento de finalizarse la animación. Es decir, cómo quedará todo tras la ejecución de cada fotograma.

Cómo animar un gráfico en SVG

El dibujo se compone de tres animaciones diferentes: el texto que aparece de izquierda a derecha, los óvalos que crecen y las elipses que aparecen donde terminan los óvalos.

Cada uno de estos componentes tienen asociados una clase css: .oval-n (donde 'n' es un número diferente según cada óvalo), .ellipse y .text .
Lo primero que definiremos son los atributos STROKE o trazo: stroke-dasharray (Patrón o línea continúa, discontinúa...) y stroke-dashoffset (Distancia en la que comenzará el patrón):

.oval-4, .oval-3, .oval-2, .oval-1{    
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
}

Continuamos creando la animación, que está compuesta por:

  • Nombre de la animación (dash)
  • Duración
  • Cubic-beizer. Nos permite indicar el efecto de la transición (p.ej. rápida al principio y que se ralentice hasta el final)
  • Animation-delay (Especifica el tiempo que tardará en comenzar la animación)
  • Animation-duration  (En nuestro caso, el valor será forwards, lo que significa que el fotograma se ejecutará al 100% y conservará ese valor)

Todas estas características juntas, nos dan como resultado este código:

.oval {    
  animation: dash 2s cubic-bezier(0.4, 0, 1, 1) .4s forwards;
}

@keyframes dash {  
  to {
    stroke-dashoffset: 1; /* Finish state. Oval completed */
  }
}

Ahora animaremos las elipses. La única diferencia entre cada una de ellas es la opacidad, que cambia de 0 a 1:

.ellipse {
    opacity: 0;
    animation: appear 1s cubic-bezier(0.4, 0, 1, 1) 1.8s forwards;
}

@keyframes appear {
    to   { opacity: 1; }
}

La última animación de la que se compone nuestro diseño es la del texto. Éste aparece de izquierda a derecha cambiando su opacidad, por lo que se combinan dos animaciones:

El movimiento se realiza desde una posición en el eje de x de -50px y desde donde el texto parte con opacidad 0 (no se ve), la animación del movimiento la llamamos toRight  y lo único que indicamos es el punto final del eje x  0, dado que la posición final será la que nos muestra el diseño.

.text {
    transform: translateX(-50px);
    opacity: 0;
    animation: toRight .5s ease-out forwards, appear .5s ease-out forwards;
}

@keyframes appear {
    to   { opacity: 1; }
}

@keyframes toRight{
    to{
        transform: translateX(0); /* Finish position*/
    }

}

En conjunto, obtenemos este código:

.oval-4, .oval-2, .oval-1, .oval-3 {    
  stroke-dasharray: 1200;
  stroke-dashoffset: 1200;
  animation: dash cubic-bezier(0.4, 0, 1, 1) .4s forwards;
}

.oval-4 {    
  animation-duration: 2s;
}

.oval-3 {
  animation-duration: 1.85s;
}

.oval-2 {
  animation-duration: 3.15s;
}

.oval-1 {
    animation-duration: 3s;
}

.ellipse {
    opacity: 0;
    animation: appear 1s cubic-bezier(0.4, 0, 1, 1) 1.8s forwards;
}

.text {
    transform: translateX(-50px);
    opacity: 0;
    animation: toRight .5s ease-out forwards, appear .5s ease-out forwards;
}

@keyframes dash {  
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes appear {
    to   { opacity: 1; }
}

@keyframes toRight{
    to{
        transform: translateX(0);
    }

}


Esperamos que os sirva de ayuda :)