SVG y CSS estaban destinados a ser ♥. En este tutorial vamos a aprender a dibujar una simple forma SVG y animar el trazo de esa forma para crear un spinner de carga.
Escribiremos en SCSS para agilizar el estilo.
El código HTML/SVG es sencillo; nuestro objetivo es dibujar un círculo de 40px de ancho. Los únicos atributos aquí son las coordenadas x e y (punto de origen) y el radio.
Para tener en cuenta el grosor del trazo cuando lo añadamos después, el radio r será de 18 en lugar de 20.
<svg class="spinner">
<circle cx="20" cy="20" r="18"></circle>
</svg>
El spinner está tomando forma, pero antes de animarlo necesitamos aplicar algunos estilos más. El efecto de «crecimiento y retracción» se crea utilizando un trazo ancho. El trazo se «empuja» alrededor de la trayectoria del círculo aumentando el desplazamiento entre guiones.
Para crear el trazo ancho de guiones utilizaremos la propiedad stroke-dasharray. Al establecerla como π × radio se crea un guión con una longitud igual a la circunferencia del círculo. Por ahora, esto aparecerá como un trazo sólido.
svg.spinner {
... circle {
...
stroke-dasharray: (3.14 * $spinnerSize);
}
}
Por último, tenemos que establecer las propiedades transform-origin y animation. Establecer el origen de la transformación en el centro del círculo asegura que girará uniformemente. La propiedad animation utilizará el nombre de la animación del spinner, al que le pondremos un fotograma clave a continuación.
svg.spinner {
... circle {
...
transform-origin: (0.5px * $spinnerSize) (0.5px * $spinnerSize) 0;
animation: spinner 4s linear infinite;
}
}
Calculación de la animación
Antes establecimos el trazo a un guión con longitud igual a la circunferencia. Ahora podemos animar el desplazamiento de este trazo para «empujarlo» fuera de la trayectoria de la circunferencia.
El desplazamiento puede ser modificado usando la propiedad stroke-dashoffset. Si aumentamos el desplazamiento, el guión se retraerá, mientras que si lo reducimos, volverá a crecer a lo largo de la trayectoria del círculo.
Así que hemos animado el trazo a lo largo de la trayectoria del círculo – esa era la parte difícil. Pero, como un spinner de carga, el trazo que se retrae no es exactamente lo que buscamos. Queremos que parezca que hay una progresión constante – para crear la ilusión de que el trazo siempre se está moviendo «hacia adelante».
¿Cómo podemos hacer esto? Girando el círculo a medida que se anima el trazo.
@keyframes spinner {
0% {
...
transform: rotate(0deg);
} 50% {
...
transform: rotate(540deg);
} 100% {
...
transform: rotate(1080deg);
}
}
Nos estamos acercando, pero el girador parece ir más lento. Esto sucede cuando el golpe se mueve en contra de la dirección de rotación. Podemos contrarrestar esto rotando más en la primera mitad de la animación.
@keyframes spinner {
0% {
...
transform: rotate(0deg);
} 50% {
...
transform: rotate(720deg);
} 100% {
...
transform: rotate(1080deg);
}
}
En el ejemplo de abajo hay dos spinners:
- El primero tiene la velocidad de rotación uniforme existente (no contrarresta la ‘ralentización’).
- El segundo utiliza la rotación más rápida en la primera mitad de la animación.
He añadido unos marcadores rojos como referencia de la velocidad a la que gira el spinner.
Puedes ver que el segundo spinner es mucho más suave. Esto se debe a que parece moverse a una velocidad más uniforme. Para terminar, vamos a aumentar la velocidad reduciendo la duración de la propiedad de la animación.
Más información
- MDN animation
- MDN stroke-dasharray
- MDN stroke-dashoffset