¿Qué hace swarm-build?
swarm-build es un módulo ES único sin dependencias (src/swarm-build.js, aproximadamente 600 líneas) más un archivo CSS opcional (src/swarm-build.css).
Tiene dos modos:
- Modo imagen,
swarmBuild(img): un lienzo en blanco cubre un<img>(o un elemento con unabackground-imageCSS), y cada región de la imagen aparece después de que un cursor arrastra su recuadro mostrando una etiqueta en vivoA × A. - Modo página,
swarmBuildPage("[data-swarm-block]"): los elementos marcados de una página en vivo desaparecen, luego los cursores los reconstruyen uno por uno. Los bloques de texto plano (títulos, párrafos cortos) se escriben solos. Un bloque dentro de otro espera a su contenedor. Los bloques que están debajo del pliegue esperan hasta que se vean al hacer scroll, por lo que el enjambre sigue al lector por la página.
En ambos modos, los cursores se van al final y todos los cambios realizados por la biblioteca se deshacen.
1. Instalación
Copia src/swarm-build.js, src/swarm-build.d.ts y src/swarm-build.css de este repositorio al proyecto (por ejemplo lib/swarm-build/) e impórtalos con rutas relativas.
No hay dependencias ni paso de compilación.
Solo si npm view swarm-build muestra que el paquete está publicado: npm install swarm-build, luego import { swarmBuild } from "swarm-build" y import "swarm-build/style.css".
2a. Modo página: marcar los bloques
- Lee el marcado de la página y elige los bloques que dibujaría un diseñador: barra de navegación, encabezado de héroe, párrafo de héroe, cada botón, cada tarjeta, gráfico, tabla, pie de página. Una página de inicio típica tiene de 25 a 60 bloques.
- Agrega
data-swarm-blocka cada uno.- Marca los contenedores (una tarjeta) y el texto dentro de ellos (su título y párrafo) para obtener "primero el marco, luego rellénalo".
- Marca los títulos y párrafos cortos cuyo contenido sea texto plano: esos se escriben solos. Los elementos con marcado en línea (enlaces,
<b>) se barren en su lugar. - Omite los envoltorios que solo hacen diseño (cuadrículas, secciones sin fondo propio). Ocultarlos oculta todo lo que hay dentro de una vez.
- No marques interfaces fijas o fijadas que el visitante necesite de inmediato, como un banner de cookies o un widget de chat.
- Llámalo después de que el contenido esté en el DOM:
import { swarmBuildPage } from "./lib/swarm-build/swarm-build.js";
swarmBuildPage("[data-swarm-block]", { speed: 1.5 });
Para ocultar los bloques antes de que se ejecute el script (sin destello de la página terminada), agrega también data-swarm-pending a cada bloque e incluye el archivo CSS.
2b. Modo imagen: elegir las regiones
Las regiones deciden qué se construye y en qué orden. Las buenas regiones hacen que la animación se vea intencionada, así que no te saltes este paso.
- Abre la imagen y mírala (lee el archivo de imagen o toma una captura de pantalla de la página).
- Enumera los 6 a 15 bloques significativos que dibujaría un diseñador: barra de navegación, encabezado, barra de búsqueda, tarjetas, gráfico, lista, pie de página.
- Escribe cada bloque como
x y a aen porcentaje del ancho y alto de la imagen (0 a 100). Mide a partir del tamaño en píxeles:x = izquierda / anchoImagen * 100. - Ordénalos de la forma en que una persona construiría la pantalla: primero el marco (barra, encabezado), luego el contenido de arriba a abajo.
- Deja pequeños espacios. Cualquier cosa que no cubra ninguna región aparece cuando el lienzo se desvanece al final, por lo que las regiones no necesitan cubrir cada píxel.
Ponlas en la imagen como data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, ...", o pasa regions: [{ x, y, w, h }] en JavaScript.
Sin regiones, la biblioteca usa un diseño genérico de barra lateral, encabezado y tarjetas, que rara vez coincide con la imagen.
3. Integración
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 o Next.js (componente cliente):
"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} />;
}
Para Vue, Svelte o Astro, haz lo mismo: llama a swarmBuild(el) después del montaje y a destroy() al desmontar.
Varias imágenes (por ejemplo, un iPad y un teléfono) pueden compartir un mismo enjambre: swarmBuild([ipadImg, phoneImg]).
4. Opciones
| Opción | Predeterminado | Uso |
|---|---|---|
regions (por objetivo) | data-swarm-regions, luego genérico | Qué construir, en orden |
agents | 6 nombres y colores integrados | [{ name, color, text }], que coincida con la paleta y audiencia del sitio |
speed | 1 | 2 reduce la duración a la mitad (aproximadamente 6 a 8 s en 1 para 10 a 15 regiones) |
start | "visible" | "now" comienza de inmediato en lugar de cuando la imagen aparece al hacer scroll |
canvas | "#fff" | Color del lienzo sin construir; que coincida con el fondo de la captura de pantalla |
zIndex | 2147483000 | Apilamiento de la capa fija del cursor; redúcelo si un modal o encabezado debe estar encima |
onDone | ninguno | Se llama una vez cuando la construcción se completa o se llama a finish() |
typeSpeed (modo página) | 1 | Velocidad del texto escrito; 2 escribe el doble de rápido |
El valor devuelto tiene finished, finish() y destroy():
finishedes una Promesa que siempre se resuelve, sin importar cómo termine el enjambre.finish()salta a la imagen terminada y se ejecutaonDone.destroy()elimina todo ahora yonDoneno se ejecuta. Llámalo al desmontar.setSpeed(n)cambia la velocidad mientras se ejecuta.
En modo página, start predetermina a "now"; en modo imagen, a "visible".
5. Reglas a mantener
data-swarm-pendingmás el archivo CSS mantienen la imagen oculta hasta que el script comience, por lo que no destella terminada primero. Si el script nunca se ejecuta, el CSS muestra la imagen después de 4 segundos. Omite el atributo cuando la imagen es el elemento LCP de la página y el tiempo de carga importa más que el efecto.- Movimiento reducido (
prefers-reduced-motion: reduce) muestra la imagen terminada y nunca anima. No anules esto. - Los cursores viven en una capa fija de tamaño completo encima de la página (
pointer-events: none). - Mientras se ejecuta, la biblioteca inserta una superposición justo después de la imagen, dentro del contenedor de la imagen. Si el contenedor era estático, también establece
position: relativeen él. Ambos se deshacen al final.- Dale a la imagen un contenedor de nivel de bloque propio, como un
<div>o<figure>. Los contenedores en línea como<a>o<picture>pueden descolocar la superposición. - CSS hermano como
:last-childo Tailwindspace-y-*puede cambiar brevemente mientras la superposición está allí.
- Dale a la imagen un contenedor de nivel de bloque propio, como un
- La imagen se copia como un fondo CSS estirado al cuadro de contenido de la imagen. Los bordes y el relleno en la imagen están bien, pero los recortes de
object-fit: coverocontainno se reproducen. - Bajo una CSP estricta o Trusted Types no se necesita cambios: la biblioteca construye cada elemento con llamadas DOM, establece estilos a través del CSSOM y usa
innerHTML,<style>o script en línea. La URL de la imagen debe estar permitida porimg-src.
6. Verificación
- Carga la página y observa una construcción completa. Cada recuadro debe aterrizar en un bloque real de la interfaz de la imagen, no en espacio vacío ni atravesando dos bloques.
- Comprueba un ancho de teléfono (375 píxeles). Las insignias y etiquetas de nombre tienen un tamaño fijo, por lo que las imágenes muy pequeñas pueden sentirse abarrotadas; usa menos regiones, más grandes allí.
- Activa el movimiento reducido en el sistema operativo o en las herramientas de desarrollo del navegador: la imagen debe mostrarse de inmediato, sin cursores.
- Revisa la consola en busca de errores y que no queden elementos del enjambre con
aria-hiddenen el DOM después de que termine.
