Was macht swarm-build?
swarm-build ist ein abhängigkeitsfreies ES-Modul (src/swarm-build.js, ca. 600 Zeilen) plus einer optionalen CSS-Datei (src/swarm-build.css).
Es bietet zwei Modi:
- Bildmodus,
swarmBuild(img): Eine leere Leinwand bedeckt ein<img>(oder ein Element mit einem CSS-background-image), und jede Region erscheint, nachdem ein Cursor ihr Kästchen mit einem Live-B × H-Label herausgezogen hat. - Seitenmodus,
swarmBuildPage("[data-swarm-block]"): Die markierten Elemente einer Live-Seite verschwinden, dann bauen die Cursor sie nacheinander wieder auf. Reine Textblöcke (Überschriften, kurze Absätze) tippen sich selbst ein. Ein Block innerhalb eines anderen Blocks wartet auf seinen Eltern-Block. Blöcke unter dem Falz warten, bis sie in den sichtbaren Bereich scrollen, so dass der Schwarm dem Leser die Seite hinunter folgt.
In beiden Modi verschwinden die Cursor am Ende, und alle Änderungen, die die Bibliothek vorgenommen hat, werden rückgängig gemacht.
1. Installation
Kopieren Sie src/swarm-build.js, src/swarm-build.d.ts und src/swarm-build.css aus diesem Repository in Ihr Projekt (z.B. lib/swarm-build/) und importieren Sie sie mit relativen Pfaden.
Es gibt keine Abhängigkeiten und keinen Build-Schritt.
Nur wenn npm view swarm-build anzeigt, dass das Paket veröffentlicht ist: npm install swarm-build, dann import { swarmBuild } from "swarm-build" und import "swarm-build/style.css".
2a. Seitenmodus: Blöcke markieren
- Lesen Sie das Markup der Seite und wählen Sie die Blöcke aus, die ein Designer zeichnen würde: Navigationsleiste, Hero-Überschrift, Hero-Absatz, jeden Button, jede Karte, Diagramm, Tabelle, Fußzeile. Eine typische Landingpage hat 25 bis 60.
- Fügen Sie zu jedem
data-swarm-blockhinzu.- Markieren Sie Container (eine Karte) und den Text darin (ihre Überschrift und ihren Absatz), um „zuerst den Rahmen, dann den Inhalt“ zu erhalten.
- Markieren Sie Überschriften und kurze Absätze, deren Inhalt reiner Text ist: Diese tippen sich ein. Elemente mit Inline-Markup (Links,
<b>) erscheinen dagegen durch Einfliegen. - Überspringen Sie Wrapper, die nur Layout machen (Grids, Abschnitte ohne eigenen Hintergrund). Wenn man sie verbirgt, verbirgt man alles darin auf einmal.
- Markieren Sie keine fixierten oder sticky UI-Elemente, die der Besucher sofort braucht, wie einen Cookie-Banner oder Chat-Widget.
- Rufen Sie es auf, nachdem der Inhalt im DOM ist:
import { swarmBuildPage } from "./lib/swarm-build/swarm-build.js";
swarmBuildPage("[data-swarm-block]", { speed: 1.5 });
Um die Blöcke vor dem Skriptstart zu verstecken (kein Aufblitzen der fertigen Seite), fügen Sie außerdem data-swarm-pending zu jedem Block hinzu und binden Sie die CSS-Datei ein.
2b. Bildmodus: Regionen auswählen
Regionen bestimmen, was gebaut wird und in welcher Reihenfolge. Gute Regionen machen die Animation absichtlich aussehend, also überspringen Sie diesen Schritt nicht.
- Öffnen Sie das Bild und betrachten Sie es (lesen Sie die Bilddatei oder machen Sie einen Screenshot der Seite).
- Listen Sie die 6 bis 15 sinnvollen Blöcke auf, die ein Designer zeichnen würde: Navigationsleiste, Kopfzeile, Suchleiste, Karten, Diagramm, Liste, Fußzeile.
- Schreiben Sie jeden Block als
x y b hin Prozent der Bildbreite und -höhe (0 bis 100). Messen Sie anhand der Pixelgröße:x = links / bildBreite * 100. - Ordnen Sie sie so, wie eine Person den Bildschirm aufbauen würde: zuerst das Chrome (Leiste, Kopfzeile), dann den Inhalt von oben nach unten.
- Lassen Sie kleine Lücken. Was keine Region abdeckt, erscheint, wenn die Leinwand am Ende ausgeblendet wird. Die Regionen müssen nicht jedes Pixel abdecken.
Setzen Sie sie auf das Bild als data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, ..." oder übergeben Sie regions: [{ x, y, w, h }] in JavaScript.
Ohne Regionen verwendet die Bibliothek ein generisches Layout mit Seitenleiste, Kopfzeile und Karten, das selten zum Bild passt.
3. Einbinden
Reines HTML:
<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 oder Next.js (Client-Komponente):
"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} />;
}
Für Vue, Svelte oder Astro machen Sie dasselbe: Rufen Sie swarmBuild(el) nach dem Mounten und destroy() beim Unmounten auf.
Mehrere Bilder (z.B. ein iPad und ein Telefon) können einen Schwarm teilen: swarmBuild([ipadImg, phoneImg]).
4. Optionen
| Option | Standard | Verwendung |
|---|---|---|
regions (pro Ziel) | data-swarm-regions, dann generisch | Was gebaut werden soll, in Reihenfolge |
agents | 6 eingebaute Namen und Farben | [{ name, color, text }], an die Palette und Zielgruppe der Website anpassen |
speed | 1 | 2 halbiert die Dauer (ca. 6 bis 8 s bei 1 für 10 bis 15 Regionen) |
start | "visible" | "now" startet sofort statt wenn das Bild in den sichtbaren Bereich scrollt |
canvas | "#fff" | Farbe der ungebauten Leinwand; an den Hintergrund des Screenshots anpassen |
zIndex | 2147483000 | Stapelung der fixierten Cursor-Ebene; verringern, wenn ein Modal oder Header oben bleiben muss |
onDone | keiner | Wird einmal aufgerufen, wenn der Bau abgeschlossen ist oder finish() aufgerufen wird |
typeSpeed (Seitenmodus) | 1 | Geschwindigkeit des getippten Textes; 2 tippt doppelt so schnell |
Der Rückgabewert hat finished, finish() und destroy():
finishedist ein Promise, das immer aufgelöst wird, wie auch immer der Schwarm endet.finish()springt zum fertigen Bild, undonDonewird ausgeführt.destroy()entfernt alles sofort, undonDonewird nicht ausgeführt. Rufen Sie es beim Unmounten auf.setSpeed(n)ändert die Geschwindigkeit während der Ausführung.
Im Seitenmodus ist der Standard von start "now", im Bildmodus "visible".
5. Zu beachtende Regeln
data-swarm-pendingzusammen mit der CSS-Datei hält das Bild versteckt, bis das Skript startet, so dass es nicht zuerst fertig aufblitzt. Wenn das Skript nie läuft, zeigt das CSS das Bild nach 4 Sekunden an. Lassen Sie das Attribut weg, wenn das Bild das LCP-Element der Seite ist und die Ladezeit wichtiger ist als der Effekt.- Verminderte Bewegung (
prefers-reduced-motion: reduce) zeigt das fertige Bild an und animiert nie. Überschreiben Sie dies nicht. - Cursor leben in einer fixierten, vollflächigen Viewport-Ebene über der Seite (
pointer-events: none). - Während der Ausführung fügt die Bibliothek einen Overlay direkt nach dem Bild innerhalb des Eltern-Elements des Bildes ein. Wenn das Elternelement statisch war, setzt sie zusätzlich
position: relativedarauf. Beides wird am Ende rückgängig gemacht.- Geben Sie dem Bild ein eigenes block-level Elternelement, wie einen
<div>oder<figure>. Inline-Eltern wie<a>oder<picture>können den Overlay falsch positionieren. - Geschwister-CSS wie
:last-childoder Tailwindspace-y-*können sich kurz ändern, während der Overlay vorhanden ist.
- Geben Sie dem Bild ein eigenes block-level Elternelement, wie einen
- Das Bild wird als CSS-Hintergrund kopiert, der auf die Inhaltsbox des Bildes gestreckt wird. Ränder und Padding am Bild sind in Ordnung, aber
object-fit: coverodercontain-Zuschnitte werden nicht reproduziert. - Unter einem strengen CSP oder Trusted Types ist keine Änderung erforderlich: Die Bibliothek erstellt jedes Element mit DOM-Aufrufen, setzt Styles über das CSSOM und verwendet kein
innerHTML,<style>oder Inline-Script. Die Bild-URL muss vonimg-srcerlaubt sein.
6. Überprüfung
- Laden Sie die Seite und sehen Sie sich einen vollständigen Bau an. Jedes Kästchen sollte auf einem echten UI-Block des Bildes landen, nicht auf leerem Raum oder quer über zwei Blöcken.
- Überprüfen Sie eine Telefonbreite (375px). Labels und Namensschilder haben eine feste Größe, daher können sehr kleine Bilder überladen wirken; verwenden Sie dort weniger, größere Regionen.
- Aktivieren Sie verminderte Bewegung im Betriebssystem oder in den Browser-Entwicklertools: Das Bild muss sofort erscheinen, ohne Cursor.
- Überprüfen Sie die Konsole auf Fehler und dass keine
aria-hiddenSchwarm-Elemente im DOM zurückbleiben, nachdem es fertig ist.
