Dans cet article, je vais vous expliquer comment convertir des animations créées à l’aide de GSAP en GIF animés en utilisant gif-moderne.
Voici un aperçu de celui que j’ai réalisé plus tôt. 👇

Sur les liens ci-dessous, vous trouverez un aperçu en direct et tout le code auquel je ferai référence tout au long de cet article :
Il y a deux « pages » dans le dépôt. indice contient tout le code du GIF vu ci-dessus, et simple est un point de départ pour les étapes couvertes dans cet article.
Table des matières
Comment convertir des animations GSAP en GIF
La méthode que j’utilise pour convertir une animation GSAP en GIF consiste à capturer des données SVG à chaque « mise à jour » du Tween et à les écrire sur un canevas HTML. Une fois l’interpolation terminée, je suis alors en mesure de convertir les données SVG en données d’image rastérisées qui peuvent être utilisées par gif-moderne pour créer chaque image d’un GIF animé.
Commencer
Voici le code que j’ai utilisé dans l’exemple simple, et c’est ce que je vais utiliser pour expliquer chacune des étapes requises pour créer un GIF animé à partir d’une animation GSAP :
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Simple</title>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let animationFrames = [];
let canvasFrames = [];
gsap.timeline({
onUpdate: () => {},
onComplete: () => {},
})
.fromTo('#rect', { x: -50 }, { duration: 2, x: 350, ease: 'power.ease2' });
</script>
</head>
<body>
<main>
<section>
<svg
id='svg'
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 400 200'
width={400}
height={200}
style={{ border: '1px solid red' }}
>
<rect id='rect' x='0' y='75' width='50' height='50' fill='red'></rect>
</svg>
<canvas id='canvas' style={{ border: '1px solid blue' }} width={400} height={200}></canvas>
<img id='image' width={400} height={200} style={{ border: '1px solid green' }} />
<a id='link' download='simple.gif'>Download</a>
</section>
</main>
<script src='https://unpkg.com/modern-gif'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js'></script>
</body>
</html>
Il y a quelques choses que j’aimerais expliquer à propos du code ci-dessus.
Script en ligne
En haut du fichier, je crée une référence au canvas
élément dans le code HTML (ci-dessous) et définissez une nouvelle référence au contexte du canevas appelée ctx
. Cela me permettra de référencer l’élément canvas et d’y écrire des données.
Deux tableaux sont définis pour contenir les données capturées (j’expliquerai où chacun est utilisé dans une étape ultérieure) :
animationFrames
canvasFrames
Et enfin, mais non des moindres, une instance d’une chronologie GSAP et d’un Tween qui anime un fichier SVG. rect
élément dans le HTML (ci-dessous).
HTML
- Le HTML contient un
svg
élément avec un ID de svg
avec un rouge rect
élément avec un ID de rect
. Le rect
est l’élément que je vais animer. - Sous le
svg
l’élément est un canvas
élément. C’est ici que j’écrirai les données SVG capturées pour une utilisation ultérieure. - Sous le
canvas
l’élément est un img
élément. C’est ici que le GIF animé final sera affiché. - Enfin, il existe un élément a qui peut être utilisé pour « télécharger » le GIF.
Éléments de script
Les deux éléments de script en bas concernent la bibliothèque modern-gif et la bibliothèque GSAP. Les deux doivent être inclus dans la page pour que vous puissiez les utiliser.
Capturer des données SVG
Localisez la chronologie GSAP et apportez les modifications suivantes :
gsap.timeline({
onUpdate: () => {
+ const xml = new XMLSerializer().serializeToString(svg);
+ const src = `data:image/svg+xml;base64,${btoa(xml)}`;
+ animationFrames.push(src);
},
onComplete: () => {
+ console.log(animationFrames);
},
})
.fromTo('#rect', { x: -50 }, { duration: 2, x: 350, ease: 'power.ease2' });
Le code ci-dessus sérialise le HTML svg
élément et convertit les données en un svg+xml;base64
chaîne. À ce stade, les « données d’image » ne sont pas tout à fait ce dont j’ai besoin, mais en les convertissant en chaîne, je peux les stocker dans le animationFrame
tableau pour une utilisation ultérieure.
Si vous avez ajouté le console.log
dans le onComplete
fonction, vous devriez voir quelque chose de similaire à l’image ci-dessous dans la console de votre navigateur.

Convertir des données SVG en données rastérisées
gsap.timeline({
onUpdate: () => {
const xml = new XMLSerializer().serializeToString(svg);
const src = `data:image/svg+xml;base64,${btoa(xml)}`;
animationFrames.push(src);
},
onComplete: () => {
- console.log(animationFrames);
+ let inc = 0;
+ const renderSvgDataToCanvas = () => {
+ const virtualImage = new Image();
+ virtualImage.src = animationFrames[inc];
+ virtualImage.onload = () => {
+ ctx.clearRect(0, 0, 400, 200);
+ ctx.drawImage(virtualImage, 0, 0, 400, 200);
+ canvasFrames.push(canvas.toDataURL('image/jpeg'));
+ inc++;
+ if (inc < animationFrames.length - 1) {
+ renderSvgDataToCanvas();
+ } else {
+ console.log(canvasFrames);
+ }
+ };
+ };
+ renderSvgDataToCanvas();
},
})
.fromTo('#rect', { x: -50 }, { duration: 2, x: 350, ease: 'power.ease2' });
Cette étape est légèrement plus complexe et nécessite que j’effectue une action pour chaque index du animationFrames
tableau.
En utilisant une fonction récursive, renderSvgDataToCanvas
je peux utiliser les données d’image du animationFrames
tableau, écrivez-le sur le canevas. Ensuite, en utilisant canvas.toDataURL('image/jpeg')
Je peux stocker les données pixellisées de chaque image de l’animation dans le canvasFrames
tableau.
Si vous avez ajouté le console.log
dans le onComplete
fonction, vous devriez voir quelque chose de similaire à celui ci-dessous dans la console de votre navigateur. Cette fois, notez cependant le type MIME des données : au lieu de svg+xml
c’est image/jpeg
. C’est important pour ce que je dois faire ensuite.

Convertir des données rastérisées en GIF
Il s’agit de la dernière étape et consiste à transmettre chaque index du canvasFrames
tableau sur modern-gif.
gsap.timeline({
onUpdate: () => {
const xml = new XMLSerializer().serializeToString(svg);
const src = `data:image/svg+xml;base64,${btoa(xml)}`;
animationFrames.push(src);
},
onComplete: () => {
let inc = 0;
const renderSvgDataToCanvas = () => {
const virtualImage = new Image();
virtualImage.src = animationFrames[inc];
virtualImage.onload = () => {
ctx.clearRect(0, 0, 400, 200);
ctx.drawImage(virtualImage, 0, 0, 400, 200);
canvasFrames.push(canvas.toDataURL('image/jpeg'));
inc++;
if (inc < animationFrames.length - 1) {
renderSvgDataToCanvas();
} else {
- console.log(canvasFrames);
+ generateGif();
}
};
};
+ const generateGif = async () => {
+ const gif = await modernGif.encode({
+ width: 400,
+ height: 200,
+ frames: canvasFrames.map((frame) => {
+ return { imageData: frame, delay: 0 };
+ }),
+ });
+ const frames = await gif;
+ const blob = new Blob([frames], { type: 'image/gif' });
+ const src = URL.createObjectURL(blob);
+ const image = document.getElementById('image');
+ const link = document.getElementById('link');
+ image.src = src;
+ link.href = src;
+ };
renderSvgDataToCanvas();
},
})
.fromTo('#rect', { x: -50 }, { duration: 2, x: 350, ease: 'power.ease2' });
En utilisant moderneGif.encode vous pouvez transmettre un tableau de données sur des images et définir un délai pour chaque image, j’ai choisi d’ajouter un délai de 0 seconde.
La partie suivante du code traite de la conversion du modernGif.ecode
données et en les convertissant en « encore un autre » type MIME, cette fois image/gif
.
Une fois que j’ai un « blob » final de données qui représente mon GIF animé, je le convertis en URL, puis je définis le src
et href
de l’image et des éléments de lien afin que je puisse voir et télécharger le GIF dans le navigateur.

Fréquence d’images
Vous remarquerez peut-être que le GIF final s’exécute assez lentement, car les animations exécutées dans le navigateur seront généralement lues à 60 images par seconde (ips), alors que les GIF s’exécutent généralement à une fréquence d’images beaucoup plus lente, 12 ou 24 ips.
Pour « supprimer » certaines images de l’animation, j’utilise un filtre matriciel et Opérateur de reste JavaScript pour déterminer si l’index est divisible par un certain nombre, dans mon cas, j’ai choisi 6. Les index qui ne sont pas divisibles par 6 sont filtrés du tableau. Le GIF animé résultant, bien qu’un peu maladroit, sera lu beaucoup plus rapidement.
const generateGif = async () => {
const gif = await modernGif.encode({
width: 400,
height: 200,
frames: canvasFrames
+ .filter((_, index) => index % 6 === 0)
.map((frame) => {
return { imageData: frame, delay: 0 };
}),
});
const frames = await gif;
const blob = new Blob([frames], { type: 'image/gif' });
const src = URL.createObjectURL(blob);
const image = document.getElementById('image');
const link = document.getElementById('link');
image.src = src;
link.href = src;
};
Et c’est ainsi que vous pouvez passer de l’animation GSAP SVG au GIF animé via le canevas HTML !
Si vous avez des questions sur tout ce que j’ai décrit dans cet article, n’hésitez pas à me trouver sur Twitter/X : @PaulieScanlon.
janvier 6, 2024
Comment créer des GIF animés à partir d’animations GSAP —
Dans cet article, je vais vous expliquer comment convertir des animations créées à l’aide de GSAP en GIF animés en utilisant gif-moderne.
Voici un aperçu de celui que j’ai réalisé plus tôt. 👇
Sur les liens ci-dessous, vous trouverez un aperçu en direct et tout le code auquel je ferai référence tout au long de cet article :
Il y a deux « pages » dans le dépôt. indice contient tout le code du GIF vu ci-dessus, et simple est un point de départ pour les étapes couvertes dans cet article.
Table des matières
Comment convertir des animations GSAP en GIF
La méthode que j’utilise pour convertir une animation GSAP en GIF consiste à capturer des données SVG à chaque « mise à jour » du Tween et à les écrire sur un canevas HTML. Une fois l’interpolation terminée, je suis alors en mesure de convertir les données SVG en données d’image rastérisées qui peuvent être utilisées par gif-moderne pour créer chaque image d’un GIF animé.
Commencer
Voici le code que j’ai utilisé dans l’exemple simple, et c’est ce que je vais utiliser pour expliquer chacune des étapes requises pour créer un GIF animé à partir d’une animation GSAP :
Il y a quelques choses que j’aimerais expliquer à propos du code ci-dessus.
Script en ligne
En haut du fichier, je crée une référence au
canvas
élément dans le code HTML (ci-dessous) et définissez une nouvelle référence au contexte du canevas appeléectx
. Cela me permettra de référencer l’élément canvas et d’y écrire des données.Deux tableaux sont définis pour contenir les données capturées (j’expliquerai où chacun est utilisé dans une étape ultérieure) :
animationFrames
canvasFrames
Et enfin, mais non des moindres, une instance d’une chronologie GSAP et d’un Tween qui anime un fichier SVG.
rect
élément dans le HTML (ci-dessous).HTML
svg
élément avec un ID desvg
avec un rougerect
élément avec un ID derect
. Lerect
est l’élément que je vais animer.svg
l’élément est uncanvas
élément. C’est ici que j’écrirai les données SVG capturées pour une utilisation ultérieure.canvas
l’élément est unimg
élément. C’est ici que le GIF animé final sera affiché.Éléments de script
Les deux éléments de script en bas concernent la bibliothèque modern-gif et la bibliothèque GSAP. Les deux doivent être inclus dans la page pour que vous puissiez les utiliser.
Capturer des données SVG
Localisez la chronologie GSAP et apportez les modifications suivantes :
Le code ci-dessus sérialise le HTML
svg
élément et convertit les données en unsvg+xml;base64
chaîne. À ce stade, les « données d’image » ne sont pas tout à fait ce dont j’ai besoin, mais en les convertissant en chaîne, je peux les stocker dans leanimationFrame
tableau pour une utilisation ultérieure.Si vous avez ajouté le
console.log
dans leonComplete
fonction, vous devriez voir quelque chose de similaire à l’image ci-dessous dans la console de votre navigateur.Convertir des données SVG en données rastérisées
Cette étape est légèrement plus complexe et nécessite que j’effectue une action pour chaque index du
animationFrames
tableau.En utilisant une fonction récursive,
renderSvgDataToCanvas
je peux utiliser les données d’image duanimationFrames
tableau, écrivez-le sur le canevas. Ensuite, en utilisantcanvas.toDataURL('image/jpeg')
Je peux stocker les données pixellisées de chaque image de l’animation dans lecanvasFrames
tableau.Si vous avez ajouté le
console.log
dans leonComplete
fonction, vous devriez voir quelque chose de similaire à celui ci-dessous dans la console de votre navigateur. Cette fois, notez cependant le type MIME des données : au lieu desvg+xml
c’estimage/jpeg
. C’est important pour ce que je dois faire ensuite.Convertir des données rastérisées en GIF
Il s’agit de la dernière étape et consiste à transmettre chaque index du
canvasFrames
tableau sur modern-gif.En utilisant moderneGif.encode vous pouvez transmettre un tableau de données sur des images et définir un délai pour chaque image, j’ai choisi d’ajouter un délai de 0 seconde.
La partie suivante du code traite de la conversion du
modernGif.ecode
données et en les convertissant en « encore un autre » type MIME, cette foisimage/gif
.Une fois que j’ai un « blob » final de données qui représente mon GIF animé, je le convertis en URL, puis je définis le
src
ethref
de l’image et des éléments de lien afin que je puisse voir et télécharger le GIF dans le navigateur.Fréquence d’images
Vous remarquerez peut-être que le GIF final s’exécute assez lentement, car les animations exécutées dans le navigateur seront généralement lues à 60 images par seconde (ips), alors que les GIF s’exécutent généralement à une fréquence d’images beaucoup plus lente, 12 ou 24 ips.
Pour « supprimer » certaines images de l’animation, j’utilise un filtre matriciel et Opérateur de reste JavaScript pour déterminer si l’index est divisible par un certain nombre, dans mon cas, j’ai choisi 6. Les index qui ne sont pas divisibles par 6 sont filtrés du tableau. Le GIF animé résultant, bien qu’un peu maladroit, sera lu beaucoup plus rapidement.
Et c’est ainsi que vous pouvez passer de l’animation GSAP SVG au GIF animé via le canevas HTML !
Si vous avez des questions sur tout ce que j’ai décrit dans cet article, n’hésitez pas à me trouver sur Twitter/X : @PaulieScanlon.
Source link
Partager :
Articles similaires