Mi lucha por usar y animar un degradado cónico en SVG

La maravillosa empresa para la que trabajo, Payoneer , tiene un nuevo logotipo y mi trabajo consistía en recrearlo y animarlo para un componente de carga en nuestra aplicación. Explicaré exactamente cómo lo hice, compartiré los problemas que tuve y te guiaré a través de la solución que se me ocurrió. Y, como beneficio adicional, ¡veremos cómo animarlo!
Pero primero, supongo que algunos de vosotros os estaréis preguntando… ¿Recrearlo? ¿Por qué?
La agencia de branding que diseñó nuestro logotipo nos envió un conjunto completo de recursos categorizados por temas. Los había en todos los tamaños y en todos los formatos disponibles. Teníamos todo, incluidos SVG, para el logotipo y la animación del cargador. Pero no pudimos usarlos.
Este es el por qué. Echemos un vistazo al logotipo:
El logo es un anillo con un degradado cónico que consta de cinco colores, y… eso es todo. El problema es que SVG no admite gradientes en ángulo (al menos por ahora), por lo que cuando exportamos un diseño que tiene un gradiente cónico como SVG, necesitamos algún tipo de truco para obtener el resultado deseado.
Ahora bien, no soy un experto cuando se trata de trabajar con software de gráficos vectoriales, por lo que podría haber una forma diferente (y quizás mejor) de hacerlo, pero sé que la forma más común de exportar gradientes cónicos a SVG es convertir el elemento degradado a una imagen e inserte esa imagen en el SVG como una cadena base64. Eso también lo obtuvimos de la agencia de branding, y confío en que sabrán cuál es la mejor manera de exportar un SVG.
Pero, dado que el archivo SVG final ahora contiene una cadena PNG base64, el tamaño del archivo saltó a casi 1 MB, lo que puede no ser un desastre total, pero es mucho más alto que los 2 KB que debería ser. Multiplique esa diferencia por tres temas (sin texto, texto claro y variaciones de texto oscuro), y veremos 3 MB de imágenes en lugar de 3 KB de código. Esa es una gran diferencia, por eso hemos decidido recrear el logotipo con SVG.
¡¿Pero cómo?!
Aunque CSS es totalmente compatible con gradientes cónicos , SVG no. Entonces, la primera pregunta que me hice fue cómo crear un degradado cónico en SVG. De hecho, le pregunté a Google. Y lo que encontré fueron muchas formas interesantes, únicas y creativas de agregar gradientes cónicos a SVG, la mayoría de ellas basadas en algún tipo de clip-path
implementación. Primero creé un corto path
que representa la forma del anillo y lo usé como clip-path
un elemento simple rect
.
A continuación, necesitaba llenarlo rect
con degradados cónicos, pero primero tenía que encontrar todas las paradas de color correctas para recrear el aspecto. Me llevó un tiempo, pero después de muchos ajustes, obtuve un resultado con el que estoy contento:
div.gradient { background-image: conic-gradient(from 270deg, #ff4800 10%, #dfd902 35%, #20dc68, #0092f4, #da54d8 72% 75%, #ff4800 95%);}
El último paso fue reemplazar el rect
con algo más que admita gradientes cónicos, y la forma más sencilla que encontré es usar un foreignObject
elemento SVG con un elemento regular div
en su interior y un conic-gradient
como background-image
. Luego todo lo que tenía que hacer era configurar clip-path
el foreignObject
elemento, y eso es todo.
Así es como utilicé un degradado cónico en un SVG para mantener el diseño completamente vectorial y escalable con menos de 20 líneas de código y menos de 2 KB de tamaño de archivo.
Pero esa fue la parte fácil. Ahora hablemos de animación.
el cargador
Nuestra aplicación muestra una animación de carga cada vez que un usuario inicia sesión. Habíamos estado usando un archivo GIF para ello, pero tenía la intención de actualizarlo a una animación CSS/SVG pura durante meses. Los beneficios son obvios: un renderizado más rápido significa una experiencia de carga más fluida y un tamaño de archivo más pequeño significa una carga aún más rápida. Simplemente obtenemos más por menos, lo cual es especialmente ideal para una animación de carga.
Aquí está la animación que buscaba:
Este tipo de animación es bastante fácil con SVG. Todo lo que realmente necesitamos es un truco usando stroke-dasharray
y stroke-dashoffset
. Ese fue mi punto de partida. Creé un nuevo path
en el centro del anillo, eliminé el fill
, agregué un stroke
con la derecha stroke-width
y luego trabajé en la animación.
Me tomó un poco de juego conseguir el movimiento tal como lo querían los diseñadores. En realidad, terminé usando dos animaciones: una controla el stroke-dashoffset
y la segunda gira todo path
un giro completo.
Pero, dado que la clip-path
propiedad se refiere a fill
la forma, animar el trazo significaba que tenía que resolver uno de dos problemas: podía encontrar una manera diferente de animar el movimiento o encontrar una manera diferente de agregar los colores al trazo.
Así que volví a Google y a todas las ideas creativas que encontré antes, pero la mayoría de ellas eran prácticamente no animables, así que comencé a buscar una buena forma clip-path
de agregar colores al trazo. Miré algunas soluciones “listas para usar”, revisé el enmascaramiento y terminé con la solución perfecta más simple:
.logoBlend { mix-blend-mode: lighten;}
Un lighten
modo de fusión analiza los colores RGB de cada píxel del elemento renderizado, lo compara con el valor RGB del píxel de fondo que está detrás de él y mantiene el que sea más alto. Eso significa que las partes del elemento que son blancas permanecerán blancas y las partes oscuras obtendrán los valores del píxel de fondo.
Al agregar un blanco rect
al camino negro, básicamente bloqueé todo lo que esté detrás de él. Mientras tanto, todo lo que hay detrás del trazo negro animado es visible. Eso significaba que podía recuperar el foreignObject
con el conic-gradient
, colocarlo detrás de la mix-blend-mode
capa y darle una animación de rotación simple para que coincidiera con el diseño.
Note that the end result of this method will have a white background, not transparent like the static logo, but I was fine with that. If you need to, you can flip it around, use black background, and hide the light parts of your element by setting the blend mode to darken
.
Final touches
I was pretty much done at this point, and quite happy with the end result. But a couple of days later, I got a Lottie-based JSON file from the branding agency with the exact same animation. In retrospect, maybe I could spare my work and use their file, it would have worked just fine. Even the file size was surprisingly small, but it was still 8✕ bigger than the SVG, so we ended up using my animation anyway.
But, that meant I had one last thing to do. The Lottie animation had a “start animation” where the small orange dot grows into view, and I had to add it to my animation as well. I added a short 0.5s delay to all three animations as well as a scaling animation in the beginning.
Click on “Rerun” on the Pen to see the animation again from the initial dot.
That’s it! Now my company has a new logo and a set of lightweight, fully scalable assets to use across our web platforms.
And for those of you wondering, yes, I did end up creating a nice little Logo component in React since we’re using it. It even renders the SVG according to a theme passed to it as a prop, making the implementation easier, and keeping all future changes in a single location.
What about you?
Do you think there’s a better way to get the same result? Share your thoughts in the comments! And thank you for reading.
Deja un comentario