1. Web Design
  2. HTML/CSS
  3. SVG

Firma en la línea de puntos: Animar tu propia firma SVG

Scroll to top

Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)

Animar el trazo de un SVG es perfecto para simular la escritura a mano. En el transcurso de dos tutoriales vamos a usar la animación CSS para hacer que una firma parezca estar realmente manuscrita, como si estuvieras firmando la página tú mismo.

Esto es lo que vamos a construir:

Please accept marketing cookies to load this content.

1. Archivo SVG

Antes de sumergirnos en cualquier código, vamos a necesitar una versión SVG de tu firma. No importa qué software utilices para hacerlo, pero trata de mantener las líneas y curvas lo más suaves posible para lograr el mejor efecto.

Aquí está la mía, que puedes ver cómo se dibuja mediante tres trazados independientes:

first signature pathfirst signature pathfirst signature path
Primer trazado
Second signature pathSecond signature pathSecond signature path
Segundo trazado
Third signature pathThird signature pathThird signature path
Tercer trazado

Asegúrate de que la mesa de trabajo esté recortada ajustándose perfectamente a la firma y, a continuación, guarda el archivo en formato SVG.

2. Ordenar el código SVG

Si abres el archivo en un editor de código verás la estructura XML del archivo SVG. Dependiendo de la aplicación que utilizases para diseñarla, además de cómo la guardases o exportases, tendrás un elemento <svg> con alguna tontería delante. Las tonterías que sobran se pueden quitar.

En este caso, los elementos con los que nos quedaremos se verán como algo así:

1
<svg>
2
    <line/>
3
    <path/>
4
    <line/>
5
</svg>

Dentro de nuestro <svg> principal tenemos un <line>, luego un <path>, luego otro <line>. Se trata de los tres objetos vectoriales que dibujamos antes, diferenciados sólo porque, técnicamente, una línea no tiene curvatura, por lo que en el archivo SVG viene definida de manera diferente a un trazado curvo, a saber "path".

3. Añadir clases

Tendremos que apuntar a estos vectores con CSS por separado un poco más adelante, así que asegúrate de que cada uno tenga un nombre de clase adecuado. Es probable que el elemento <svg> ya tenga un identificador que refleje el nombre que tenía la capa en la aplicación en la que fue diseñado.

1
<svg id="signature">
2
    <line class="stroke-I" />
3
    <path class="stroke-an" />
4
    <line class="stroke-flourish" />
5
</svg>

He nombrado mis vectores con nombres de clase relacionados con lo que son (el primero es la "I" de mi nombre, por ejemplo).

4. El resto de atributos SVG

Para ser justos, tu SVG no se verá tan limpio. Cada uno de estos vectores tendrá un montón de coordenadas, además de varios atributos enterrados dentro de ellos. Las coordenadas tendrán que quedarse, pero podemos eliminar algunos de los atributos habituales y colocarlos en cambio en nuestra hoja de estilo CSS, manteniendo las cosas bonitas y limpias.

Nuevo proyecto

Voy a construirlo usando CodePen, pero puedes usar documentos HTML y CSS independientes si lo prefieres. Pega el código SVG directamente en tu documento HTML. A continuación, quita los atributos que tienen en común cada uno de los elementos de trazado y línea , y colócalos en tu archivo de estilos CSS. Por ejemplo, habrás observado atributos como:

  • fill="none"
  • stroke="#0F436D"
  • stroke-width="2"
  • stroke-linecap="round"
  • stroke-linejoin="round"
  • stroke-miterlimit="10"

Puedes eliminar estos y añadirlos en su lugar vía CSS, de la siguiente manera:

1
path,
2
line {
3
  fill: none;
4
  stroke: #2a3745;
5
  stroke-width: 2;
6
  stroke-linecap: round;
7
  stroke-linejoin: round;
8
  stroke-miterlimit: 10;
9
}

¡Mucho más limpio!

Please accept marketing cookies to load this content.

5. Comienza a animar

Con el fin de animar los trazos de este SVG vamos a utilizar una técnica planteada por primera vez por Jake Archibald. La idea es la siguiente: a cada uno de estos vectores se le va a dar un trazo discontinuo. Para ello, aplicamos un valor de stroke-dasharray dentro del CSS:

Please accept marketing cookies to load this content.

Longitud de cada tramo del trazo discontinuo

Para cada uno de estos vectores hacemos que el stroke-dasharray tenga justamente la misma longitud que el trazado, por lo que cada uno tendrá un solo guión que cubrirá toda su longitud. Para conseguirlo se requiere un poco de prueba y error, en nuestro caso los valores serán los siguientes:

1
.stroke-I {
2
  stroke-dasharray: 80;
3
}
4
5
.stroke-an {
6
  stroke-dasharray: 360;
7
}
8
9
.stroke-flourish {
10
  stroke-dasharray: 40;
11
}

Ahora, con el fin de animar estos trazos, necesitamos desplazar cada uno de los guiones para que el espacio vacío cubra el vector, no el guión. ¿Tiene sentido? Estas ilustraciones podrían ayudar. En esta primera, imagina que la línea discontinua se está utilizando para cubrir el remate decorativo al final de la firma.

Ahora en esta hemos compensado el guión, de manera que es el hueco vacío lo que está sobre el origen:

Ahora, todo lo que tenemos que hacer es usar CSS para animar desde el estado desplazado hasta el otro.

6. Fotogramas clave

La animación CSS consiste en definir primero los fotogramas clave. Cada fotograma clave representa estados a lo largo de una línea de tiempo y, después, nuestros navegadores representan las animaciones entre ellos.

Veamos primero cómo se puede animar este desplazamiento de guión. Usaremos el primer trazo, la "I", y animaremos entre dos estados. Empieza configurando algunos fotogramas clave:

1
@keyframes write1 {
2
    0% {
3
        stroke-dashoffset: 80;
4
    }
5
    100% {
6
        stroke-dashoffset: 0;
7
    }
8
}

Aquí le damos un nombre a los fotogramas clave (write1) y usando la sintaxis abreviada especificamos que al principio de la línea de tiempo (0%) queremos que el stroke-dashoffset sea 80. En otras palabras: el guión, que es exactamente 80px de largo, será totalmente desplazado.

Al final de la línea de tiempo (al 100%) queremos que el stroke-dashoffset sea 0, por lo que el guión cubrirá una vez más el vector.

Aplicar la animación

Ahora ya tenemos nuestros fotogramas clave, vamos a vincularlos a una animación. Añadimos otra declaración a nuestra regla stroke-I:

1
.stroke-I {
2
  stroke-dasharray: 80;
3
  animation: write1 3s infinite linear;
4
}

Aquí, usando la propiedad animation, indicamos que queremos usar los fotogramas clave write1 definidos hace un momento, queremos que todo dure exactamente 3 segundos, queremos que la animación se reproduzca en bucle infinitamente y que la velocidad sea lineal (para que no haya aceleración o desaceleración).

Esto es lo que obtenemos:

Please accept marketing cookies to load this content.

Nota: Estoy usando Autoprefixer en CodePen lo que me ahorra tener que usar prefijos de navegador en el código de la animación.

Aplicar a los tres vectores

Necesitamos definir dos conjuntos más de fotogramas clave (write2 y write3) para los restantes vectores de la firma, y necesitamos crear desplazamientos con las longitudes de guión correctas que descubrimos anteriormente:

1
@keyframes write2 {
2
    0% {
3
        stroke-dashoffset: 360;
4
    }
5
    100% {
6
        stroke-dashoffset: 0;
7
    }
8
}
9
10
@keyframes write3 {
11
    0% {
12
        stroke-dashoffset: 40;
13
    }
14
    100% {
15
        stroke-dashoffset: 0;
16
    }
17
}

A continuación, tenemos que aplicar esas animaciones a los dos vectores restantes:

1
.stroke-an {
2
  stroke-dasharray: 360;
3
  animation: write2 3s infinite linear;
4
}
5
6
.stroke-flourish {
7
  stroke-dasharray: 40;
8
  animation: write3 3s infinite linear;
9
}

Esto es lo que obtenemos:

Please accept marketing cookies to load this content.

¡Ahora estamos llegando a algún lado! Cada vector se está animando perfectamente, en un movimiento lineal que dura 3 segundos.

¿El siguiente paso? Para animarlos en secuencia.

7. Animación secuencial

Actualmente tenemos tres trazos que se animan de forma simultánea. Sin embargo, idealmente queremos que la "I" se anime primero, y que luego le siga la "an", y por último la floritura final. Si tuviéramos que visualizar esto a lo largo de una línea de tiempo podría verse así:

En realidad podemos representar estas secciones de la línea de tiempo perfectamente en nuestros fotogramas clave CSS. Por ejemplo, la primera sección (del 0% al 33,3%) es cuando queremos que nuestra "I" se anime, por lo que modificamos los fotogramas clave para que terminen al 33,3% en lugar de al 100%:

1
@keyframes write1 {
2
    0% {
3
        stroke-dashoffset: 80;
4
    }
5
    33.3% {
6
        stroke-dashoffset: 0;
7
    }
8
}

Ahora, dado que las tres animaciones tienen la misma longitud (3 segundos) podemos asegurarnos de que la segunda no se inicie hasta el 33,3%, cuando se complete la primera animación:

1
@keyframes write2 {
2
    0%, 33.3%  {
3
        stroke-dashoffset: 360;
4
    }
5
    100% {
6
        stroke-dashoffset: 0;
7
    }
8
}

Esto es lo que nos da:

Please accept marketing cookies to load this content.

Completar la secuencia

Las dos primeras animaciones fluyen muy bien, así que vamos a mejorar el conjunto haciendo que la segunda termine al 66,6%, momento en el que la animación final puede iniciarse. Nuestros fotogramas clave tendrán este aspecto:

1
@keyframes write1 {
2
    0% {
3
        stroke-dashoffset: 80;
4
    }
5
    33.3% {
6
        stroke-dashoffset: 0;
7
    }
8
}
9
10
@keyframes write2 {
11
    0%, 33.3%  {
12
        stroke-dashoffset: 360;
13
    }
14
    66.6% {
15
        stroke-dashoffset: 0;
16
    }
17
}
18
19
@keyframes write3 {
20
    0%, 66.6% {
21
        stroke-dashoffset: 40;
22
    }
23
    100% {
24
        stroke-dashoffset: 0;
25
    }
26
}

Y la secuencia se verá así:

Please accept marketing cookies to load this content.

Refinado adicional

Lo que tenemos está bien, pero no es perfecto, ciertamente todavía está lejos de aparentar un movimiento realista escrito con pluma. Cada uno de estos tres vectores se está dibujando en el transcurso de un segundo, con independencia de cuál sea su longitud. El vector medio es mucho más largo que el anterior, por lo que lógicamente debería tardar más tiempo en dibujarse. Una línea de tiempo mejorada podría tener un aspecto similar al siguiente:

Para darle mayor realismo hay incluso un espacio entre el final del primer trazado vectorial y el comienzo del segundo. Así que vamos a alterar los valores de nuestros fotogramas clave para reflejar que:

1
@keyframes write1 {
2
    0% {
3
        stroke-dashoffset: 80;
4
    }
5
    20% {
6
        stroke-dashoffset: 0;
7
    }
8
}
9
10
@keyframes write2 {
11
    0%, 25%  {
12
        stroke-dashoffset: 360;
13
    }
14
    90% {
15
        stroke-dashoffset: 0;
16
    }
17
}
18
19
@keyframes write3 {
20
    0%, 90% {
21
        stroke-dashoffset: 40;
22
    }
23
    100% {
24
        stroke-dashoffset: 0;
25
    }
26
}

Por último, aceleramos las cosas cambiando todos los valores de 3s a 2s. También podemos actualizar las declaraciones de la animación para que cada una se ejecute una sola vez, no de forma infinita en bucle:

1
animation: write1 2s 1 linear;

También es posible que desees jugar con el valor lineal, en lugar añadir algún efecto tipo ease-in, ease-in-out, ease-out, etc. para hacer el movimiento menos uniforme. ¿Qué nos da todo eso?

Please accept marketing cookies to load this content.

Próxima vez

¡Hemos hecho un gran progreso y también hemos aprendido mucho a lo largo del camino! En el siguiente tutorial vamos a dar un paso más, utilizando Waypoints.js para ayudarnos a controlar cuándo tiene lugar la animación. ¡Nos vemos allí!