Que fait swarm-build ?
swarm-build est un module ES sans dépendance (src/swarm-build.js, environ 600 lignes) accompagné d'un fichier CSS optionnel (src/swarm-build.css).
Il propose deux modes :
- Mode Image,
swarmBuild(img): un canevas blanc recouvre une<img>(ou un élément avec unebackground-imageCSS), et chaque région de celle-ci se révèle après qu'un curseur a tracé sa boîte avec un badge dynamiqueL × H. - Mode Page,
swarmBuildPage("[data-swarm-block]"): les éléments marqués d'une page live disparaissent, puis les curseurs les reconstruisent un par un. Les blocs de texte brut (titres, courts paragraphes) se tapent eux-mêmes. Un bloc situé à l'intérieur d'un autre attend son parent. Les blocs situés en dessous de la ligne de flottaison attendent d'être visibles à l'écran, de sorte que l'essaim suive le lecteur qui défile.
Dans les deux modes, les curseurs disparaissent à la fin et toute modification effectuée par la bibliothèque est annulée.
1. Installation
Copiez src/swarm-build.js, src/swarm-build.d.ts et src/swarm-build.css de ce dépôt dans votre projet (par exemple lib/swarm-build/) et importez-les avec des chemins relatifs.
Il n'y a aucune dépendance et aucune étape de build.
Seulement si npm view swarm-build indique que le paquet est publié : npm install swarm-build, puis import { swarmBuild } from "swarm-build" et import "swarm-build/style.css".
2a. Mode Page : marquer les blocs
- Lisez le balisage de la page et choisissez les blocs qu'un designer dessinerait : barre de navigation, titre de hero, paragraphe de hero, chaque bouton, chaque carte, graphique, tableau, pied de page. Une page d'accueil typique en contient 25 à 60.
- Ajoutez
data-swarm-blockà chacun.- Marquez les conteneurs (une carte) et le texte à l'intérieur (son titre et son paragraphe) pour obtenir « le cadre d'abord, puis le remplissage ».
- Marquez les titres et les courts paragraphes dont le contenu est du texte brut : ceux-ci se tapent. Les éléments avec un balisage en ligne (liens,
<b>) se dévoilent. - Ignorez les wrappers qui ne font que de la mise en page (grilles, sections sans fond propre). Les masquer cache tout ce qu'ils contiennent d'un coup.
- Ne marquez pas les éléments fixes ou sticky dont le visiteur a besoin immédiatement, comme une bannière de cookies ou un widget de chat.
- Appelez la fonction après que le contenu est dans le DOM :
import { swarmBuildPage } from "./lib/swarm-build/swarm-build.js";
swarmBuildPage("[data-swarm-block]", { speed: 1.5 });
Pour masquer les blocs avant l'exécution du script (pas de flash de la page finie), ajoutez également data-swarm-pending à chaque bloc et incluez le fichier CSS.
2b. Mode Image : choisir les régions
Les régions déterminent ce qui est construit et dans quel ordre. De bonnes régions donnent à l'animation un aspect intentionnel, donc ne sautez pas cette étape.
- Ouvrez l'image et regardez-la (lisez le fichier image, ou prenez une capture d'écran de la page).
- Listez les 6 à 15 blocs significatifs qu'un designer dessinerait : rail de navigation, en-tête, barre de recherche, cartes, graphique, liste, pied de page.
- Écrivez chaque bloc comme
x y l hen pourcentage de la largeur et de la hauteur de l'image (0 à 100). Mesurez à partir de la taille en pixels :x = gauche / largeurImage * 100. - Ordonnez-les comme une personne construirait l'écran : chrome d'abord (rail, en-tête), puis le contenu de haut en bas.
- Laissez de petits espaces. Tout ce qu'aucune région ne couvre apparaît lorsque le canevas s'estompe à la fin, donc les régions n'ont pas besoin de couvrir chaque pixel.
Placez-les sur l'image avec data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, ...", ou passez regions: [{ x, y, w, h }] en JavaScript.
Sans régions, la bibliothèque utilise une disposition générique avec barre latérale, en-tête et cartes, qui correspond rarement à l'image.
3. Intégration
HTML simple :
<link rel="stylesheet" href="/lib/swarm-build/swarm-build.css" />
<img src="/shot.png" alt="..." width="1200" height="800"
data-swarm-pending
data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, 21 13 24 16" />
<script type="module">
import { swarmBuild } from "/lib/swarm-build/swarm-build.js";
swarmBuild(document.querySelector("img[data-swarm-regions]"));
</script>
React ou Next.js (composant client) :
"use client";
import { useEffect, useRef } from "react";
import { swarmBuild } from "@/lib/swarm-build/swarm-build.js";
export function BuiltImage(props: React.ComponentProps<"img"> & { regions: string }) {
const ref = useRef<HTMLImageElement>(null);
useEffect(() => {
const swarm = swarmBuild(ref.current!);
return () => swarm.destroy();
}, []);
const { regions, ...img } = props;
return <img ref={ref} {...img} data-swarm-pending="" data-swarm-regions={regions} />;
}
Pour Vue, Svelte ou Astro, faites de même : appelez swarmBuild(el) après le montage et destroy() au démontage.
Plusieurs images (par exemple un iPad et un téléphone) peuvent partager un même essaim : swarmBuild([ipadImg, phoneImg]).
4. Options
| Option | Défaut | Utilisation |
|---|---|---|
regions (par cible) | data-swarm-regions, puis générique | Ce qui doit être construit, dans l'ordre |
agents | 6 noms et couleurs intégrés | [{ name, color, text }], à adapter à la palette et à l'audience du site |
speed | 1 | 2 réduit de moitié la durée (environ 6 à 8 s à 1 pour 10 à 15 régions) |
start | "visible" | "now" démarre immédiatement au lieu de quand l'image entre dans le viewport |
canvas | "#fff" | Couleur du canevas non construit ; à adapter au fond de la capture d'écran |
zIndex | 2147483000 | Empilement de la couche fixe des curseurs ; diminuez-le si une modale ou un en-tête doit rester au-dessus |
onDone | aucun | Appelé une fois lorsque la construction se termine ou que finish() est appelé |
typeSpeed (mode Page) | 1 | Vitesse du texte tapé ; 2 tape deux fois plus vite |
La valeur de retour possède finished, finish() et destroy() :
finishedest une Promise qui se résout toujours, quelle que soit la façon dont l'essaim se termine.finish()passe directement à l'image finie, etonDones'exécute.destroy()supprime tout immédiatement, etonDonene s'exécute pas. Appelez-le au démontage.setSpeed(n)modifie la vitesse pendant l'exécution.
En mode Page, start par défaut est "now" ; en mode Image, "visible".
5. Règles à respecter
data-swarm-pendingassocié au fichier CSS maintient l'image masquée jusqu'au lancement du script, afin qu'elle n'apparaisse pas finie en premier. Si le script ne s'exécute jamais, le CSS affiche l'image après 4 secondes. Laissez cet attribut de côté lorsque l'image est le LCP de la page et que le temps de chargement importe plus que l'effet.- Mouvement réduit (
prefers-reduced-motion: reduce) affiche l'image finie et n'anime jamais. Ne remplacez pas ce comportement. - Les curseurs se situent dans une couche fixe, pleine largeur du viewport, au-dessus de la page (
pointer-events: none). - Pendant l'exécution, la bibliothèque insère une superposition juste après l'image, à l'intérieur du parent de l'image. Si le parent était statique, elle définit également
position: relativesur celui-ci. Les deux sont annulés à la fin.- Donnez à l'image un parent de type bloc qui lui est propre, comme une
<div>ou un<figure>. Les parents en ligne comme<a>ou<picture>peuvent déplacer la superposition. - Les CSS de voisinage comme
:last-childou Tailwindspace-y-*peuvent changer brièvement pendant la présence de la superposition.
- Donnez à l'image un parent de type bloc qui lui est propre, comme une
- L'image est copiée en tant que fond CSS étiré à la boîte de contenu de l'image. Les bordures et le padding sur l'image sont acceptables, mais les recadrages
object-fit: coveroucontainne sont pas reproduits. - Sous une CSP stricte ou Trusted Types, aucune modification n'est nécessaire : la bibliothèque construit chaque élément avec des appels DOM, définit les styles via le CSSOM, et n'utilise ni
innerHTML, ni<style>, ni script en ligne. L'URL de l'image doit être autorisée parimg-src.
6. Vérification
- Chargez la page et regardez une construction complète. Chaque boîte doit atterrir sur un véritable bloc UI de l'image, pas sur un espace vide ni à cheval sur deux blocs.
- Vérifiez sur une largeur de téléphone (375 px). Les badges et les étiquettes de nom ont une taille fixe, donc les très petites images peuvent sembler encombrées ; utilisez moins de régions plus grandes à cet endroit.
- Activez le mouvement réduit dans le système ou les outils de développement du navigateur : l'image doit s'afficher immédiatement, sans aucun curseur.
- Vérifiez la console pour d'éventuelles erreurs, et qu'aucun élément d'essaim avec
aria-hiddenn'est laissé dans le DOM après la fin.
