Animer du Texte avec des SVG
Les effets d’animation de textes sont aujourd’hui multiples et globalement utilisés sur les sites web modernes. Ce post a pour but de vous expliquer de la manière la plus simple possible comment créer ce genre d’effet en utilisant un avantage des chemins (paths) SVG.
Animation SVG Signature
Cet effet permet de créer des animations où le texte apparaît comme s’il était dessiné à la main, avec un contrôle précis sur chaque trait et chaque lettre.
Pourquoi utiliser des SVGs au lieu du CSS/HTML classique ?
Le CSS et les balises HTML classiques (<h1>, <p>, etc.) ne permettent pas de créer cet effet de dessin progressif pour plusieurs raisons :
Limitations du texte HTML
-
Le texte HTML est rendu comme des glyphes : Le navigateur affiche les lettres comme des formes pré-rendues (glyphes de police), pas comme des chemins animables. Une fois rendu, le texte devient une image statique.
-
Pas d’accès aux coordonnées de dessin : On ne peut pas connaître la longueur du “trait” d’une lettre pour l’animer. Le navigateur ne nous donne pas accès à ce genre d’outils.
-
Limitations CSS : Les propriétés
stroke-dasharrayetstroke-dashoffsetfonctionnent uniquement sur les éléments SVG<path>, pas sur le texte HTML. Ces propriétés sont essentielles pour créer l’effet de dessin progressif.
Avantages des chemins (paths) SVG
Les chemins SVG résolvent tous ces problèmes en représentant le texte comme des coordonnées mathématiques (attribut d), ce qui permet de :
- Calculer la longueur totale : Avec
getTotalLength(), on obtient la longueur exacte du chemin en pixels - Animer progressivement : On peut animer le trait le long du chemin de manière précise
- Contrôler chaque point : Chaque point du dessin est accessible et animable
- Créer des effets complexes : Possibilité d’animer plusieurs chemins simultanément ou séquentiellement
Les attributs clés pour l’animation :
-
stroke-dasharray: Définit le motif de tirets du trait. Par exemple,stroke-dasharray="10 5"crée des tirets de 10px suivis d’espaces de 5px. En utilisant la longueur totale du chemin comme valeur, on crée un seul long tiret qui couvre tout le chemin. -
stroke-dashoffset: Déplace le point de départ du motif de tirets le long du chemin. Une valeur positive décale le motif vers la fin du chemin, une valeur négative vers le début. En animant cette valeur de la longueur du chemin vers 0, on crée l’effet de dessin progressif.
Pour plus de détails, voir : stroke-dasharray et stroke-dashoffset sur MDN.
Mais comment convertir du texte en SVG ?
Le problème que l’on rencontre le plus rapidement en voulant faire ce genre d’animation est la conversion du texte en SVG. Pour cela il existe un merveilleux outil open source et gratuit créé par danmarshall permettant de convertir du texte en SVG : Google Font to SVG Path Converter :
Cet outil va nous permettre de :
- Sélectionner une police Google Font ou d’en importer une et entrer notre texte
- Voir le rendu de notre texte en SVG
- Voir et copier le code SVG généré
Dès que vous avez votre code SVG vous allez pouvoir passer à l’implémentation de l’animation.
Exemple Simple d’Implémentation
Voici un exemple minimaliste pour comprendre les concepts de base :
Animation SVG Simple
HTML :
<svg width="62" height="71.1" viewBox="0 0 62 71.1" xmlns="http://www.w3.org/2000/svg">
<path
class="path"
d="M 36.4 71.1 L 25.7 71.1 L 0 3.6 L 9.3 0 L 31.3 60.7 L 53.4 0.3 L 62 3.6 L 36.4 71.1 Z"
/>
</svg>
.path {
stroke: #000;
stroke-width: 0.25mm;
fill: none;
}
J’ai ici récupéré le code SVG généré par l’outil de conversion et ajouté une class à la balise <path> pour pouvoir y accéder plus facilement avec JavaScript et lui appliquer les styles CSS en lui donnant des valeurs par défaut.
JavaScript :
const path = document.querySelector('.path');
const length = path.getTotalLength();
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length; // Commence caché
const duration = 2000; // 2 secondes
const startTime = Date.now();
function animate() {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
path.style.strokeDashoffset = length * (1 - progress); // De length vers 0
if (progress < 1) {
requestAnimationFrame(animate);
}
}
animate();
Points clés à comprendre
-
getTotalLength(): Obtient la longueur totale du chemin en pixels. -
strokeDasharray = length: Crée un tiret de la même longueur que le chemin entier. -
strokeDashoffset: On anime cette valeur delength(chemin caché) vers0(chemin visible). En diminuant progressivement, le tiret “glisse” le long du chemin, révélant le dessin progressivement. -
requestAnimationFrame: Synchronise l’animation avec le navigateur (~60fps) pour une animation fluide.
Maintenant que vous avez compris le principe de base, vous pouvez passer à l’implémentation complète avec React et GSAP.
Solution complète avec React et GSAP
Il est temps de passer à l’implémentation complète avec React et GSAP de notre animation :) !
Implémentation React
"use client";
import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { useRef } from "react";
export default function AnimatedText({ height = 120 }: { height?: number }) {
const pathRefs = useRef<(SVGPathElement | null)[]>([]);
useGSAP(() => {
pathRefs.current.forEach((path) => {
if (!path) return;
const length = path.getTotalLength();
path.style.strokeDasharray = length.toString();
path.style.strokeDashoffset = length.toString();
// Dessiner le trait
gsap.to(path, {
strokeDashoffset: 0,
duration: 4,
ease: "power2.in",
});
// Remplir après que le trait soit terminé
gsap.to(path, {
delay: 2,
fill: "#FFFCF2",
duration: 2,
ease: "power2.in",
});
});
}, []);
return (
<svg width="auto" height={height} viewBox="0 0 248.295 172.203">
<path
ref={(el) => {
pathRefs.current[0] = el;
}}
fill="none"
stroke="#FFFCF2"
d="M 151.601 0 L 151.801 0.2..."
/>
</svg>
);
}
Avantages de cette Approche
useGSAP: Hook React qui gère automatiquement le nettoyage des animations lors du démontage du composant- GSAP : Bibliothèque d’animation puissante avec des easing naturels (
power2.inpour une décélération fluide) - Animation en deux étapes : D’abord le trait, puis le remplissage pour un effet complet.
Animer Plusieurs Chemins
Pour plusieurs mots ou lettres, animez-les simultanément ou séquentiellement :
// Simultané
pathRefs.current.forEach((path) => {
gsap.to(path, {
strokeDashoffset: 0,
duration: 2,
});
});
// Séquentiel
pathRefs.current.forEach((path, index) => {
gsap.to(path, {
strokeDashoffset: 0,
duration: 2,
});
});
C’est tout et c’est assez court, mais le but est de comprendre qu’il est possible de créer ce genre d’animation nativement avec du HTML et JavaScript simplement. Faites place à votre imagination et à vous de jouer :)