CommunityImagemgithub.com

swarm-build

Adicione a animação swarm-build a um site, onde um enxame de cursores nomeados e coloridos desenha caixas e constrói uma captura de tela região por região, ou reconstrói uma página inteira bloco por bloco, como um arquivo de design multiplayer. Use quando o usuário quiser que uma imagem de herói ou produto

O que é swarm-build?

swarm-build é uma biblioteca JavaScript sem dependências que cria animações de construção de interfaces web, simulando um enxame de cursores colaborativos (como no Figma) que desenham e revelam elementos de uma página ou imagem. Ela oferece dois modos principais: Image mode, onde uma imagem é revelada região por região com cursores que arrastam caixas e mostram badges de dimensão, e Page mode, onde elementos HTML marcados com `data-swarm-block` desaparecem e são reconstruídos um a um, com texto sendo digitado e blocos surgindo conforme o usuário rola a página. A biblioteca suporta frameworks populares como React, Next.js, Vue, Svelte e Astro, além de HTML puro, e é altamente configurável com opções de velocidade, cores, agentes e pontos de início. Ela respeita preferências de acessibilidade como `prefers-reduced-motion` e é segura para uso em ambientes com CSP restritivo, pois não utiliza `innerHTML` ou scripts inline.

Funciona com~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/habom2310/swarm-build/tree/HEAD/skills/swarm-build

Installed? Explore more Imagem skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Prévia

Do README da skill

swarm-build preview

Documentação

O que swarm-build faz?

swarm-build é um módulo ES sem dependências (src/swarm-build.js, cerca de 600 linhas) mais um arquivo CSS opcional (src/swarm-build.css). Possui dois modos:

  • Modo Imagem, swarmBuild(img): uma tela em branco cobre uma <img> (ou um elemento com background-image CSS), e cada região é varrida após um cursor arrastar sua caixa com um badge ao vivo L × A.
  • Modo Página, swarmBuildPage("[data-swarm-block]"): os elementos marcados de uma página ao vivo desaparecem, então os cursores os reconstroem um por um. Blocos de texto simples (títulos, parágrafos curtos) são digitados. Um bloco dentro de outro aguarda seu pai. Blocos abaixo da dobra esperam até serem rolados para visualização, então o enxame segue o leitor pela página.

Em ambos os modos, os cursores desaparecem no final e cada alteração feita pela biblioteca é desfeita.

1. Instalar

Copie src/swarm-build.js, src/swarm-build.d.ts e src/swarm-build.css deste repositório para o projeto (por exemplo, lib/swarm-build/) e importe-os com caminhos relativos. Não há dependências e nenhuma etapa de build.

Apenas se npm view swarm-build mostrar que o pacote está publicado: npm install swarm-build, depois import { swarmBuild } from "swarm-build" e import "swarm-build/style.css".

2a. Modo Página: marque os blocos

  1. Leia a marcação da página e escolha os blocos que um designer desenharia: barra de navegação, título herói, parágrafo herói, cada botão, cada cartão, gráfico, tabela, rodapé. Uma landing page típica tem de 25 a 60.
  2. Adicione data-swarm-block em cada um.
    • Marque contêineres (um cartão) e o texto dentro deles (seu título e parágrafo) para obter "moldura primeiro, depois preenchimento".
    • Marque títulos e parágrafos curtos cujo conteúdo seja texto simples: esses são digitados. Elementos com marcação inline (links, <b>) são varridos.
    • Pule wrappers que fazem apenas layout (grades, seções sem fundo próprio). Escondê-los esconde tudo dentro de uma vez.
  3. Não marque UI fixa ou sticky que o visitante precisa imediatamente, como banner de cookies ou widget de chat.
  4. Chame a função após o conteúdo estar no DOM:
import { swarmBuildPage } from "./lib/swarm-build/swarm-build.js";
swarmBuildPage("[data-swarm-block]", { speed: 1.5 });

Para esconder os blocos antes do script rodar (sem flash da página finalizada), adicione também data-swarm-pending em cada bloco e inclua o arquivo CSS.

2b. Modo Imagem: escolha as regiões

As regiões decidem o que será construído e em qual ordem. Boas regiões fazem a animação parecer intencional, então não pule esta etapa.

  1. Abra a imagem e observe-a (leia o arquivo de imagem ou tire um print da página).
  2. Liste os 6 a 15 blocos significativos que um designer desenharia: barra de navegação, cabeçalho, barra de busca, cartões, gráfico, lista, rodapé.
  3. Escreva cada bloco como x y w h em porcentagem da largura e altura da imagem (0 a 100). Meça a partir do tamanho em pixels: x = left / imageWidth * 100.
  4. Ordene-os como uma pessoa construiria a tela: chrome primeiro (barra, cabeçalho), depois conteúdo de cima para baixo.
  5. Deixe pequenos espaços. Qualquer coisa não coberta por regiões aparece quando a tela desvanece no final, então as regiões não precisam cobrir cada pixel.

Coloque-os na imagem como data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, ...", ou passe regions: [{ x, y, w, h }] em JavaScript. Sem regiões, a biblioteca usa um layout genérico de barra lateral, cabeçalho e cartões, que raramente corresponde à imagem.

3. Conecte

HTML puro:

<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 (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 ou Astro, faça o mesmo: chame swarmBuild(el) após a montagem e destroy() na desmontagem. Várias imagens (por exemplo, um iPad e um telefone) podem compartilhar um enxame: swarmBuild([ipadImg, phoneImg]).

4. Opções

OpçãoPadrãoUso
regions (por alvo)data-swarm-regions, depois genéricoO que construir, em ordem
agents6 nomes e cores embutidos[{ name, color, text }], combine com a paleta e público do site
speed12 reduz pela metade a duração (cerca de 6 a 8s em 1 para 10 a 15 regiões)
start"visible""now" inicia imediatamente em vez de quando a imagem entra na tela
canvas"#fff"Cor da tela não construída; combine com o fundo da captura de tela
zIndex2147483000Empilhamento da camada fixa de cursores; reduza se um modal ou cabeçalho precisar ficar acima
onDonenenhumChamado uma vez quando a construção completa ou finish() é chamado
typeSpeed (modo página)1Velocidade do texto digitado; 2 digita duas vezes mais rápido

O valor de retorno possui finished, finish() e destroy():

  • finished é uma Promise que sempre resolve, independentemente de como o enxame termina.
  • finish() pula para a imagem finalizada, e onDone é executado.
  • destroy() remove tudo imediatamente, e onDone não é executado. Chame-o na desmontagem.
  • setSpeed(n) altera a velocidade enquanto executa.

No modo página, start padrão é "now"; no modo imagem, "visible".

5. Regras a manter

  • data-swarm-pending mais o arquivo CSS mantêm a imagem oculta até o script iniciar, para que ela não apareça finalizada primeiro. Se o script nunca rodar, o CSS mostra a imagem após 4 segundos. Deixe o atributo de fora quando a imagem for o elemento LCP da página e o tempo de carregamento for mais importante que o efeito.
  • Movimento reduzido (prefers-reduced-motion: reduce) mostra a imagem finalizada e nunca anima. Não sobrescreva isso.
  • Os cursores vivem em uma camada fixa de viewport inteira acima da página (pointer-events: none).
  • Enquanto executa, a biblioteca insere uma sobreposição logo após a imagem, dentro do pai da imagem. Se o pai era estático, também define position: relative nele. Ambos são desfeitos no final.
    • Dê à imagem um pai de nível de bloco próprio, como uma <div> ou <figure>. Pais inline como <a> ou <picture> podem deslocar a sobreposição.
    • CSS de irmãos como :last-child ou Tailwind space-y-* podem mudar brevemente enquanto a sobreposição está presente.
  • A imagem é copiada como um background CSS esticado à caixa de conteúdo da imagem. Bordas e padding na imagem são aceitáveis, mas cortes como object-fit: cover ou contain não são reproduzidos.
  • Sob uma CSP restritiva ou Trusted Types, nenhuma alteração é necessária: a biblioteca constrói cada elemento com chamadas DOM, define estilos através do CSSOM e não usa innerHTML, <style> ou script inline. A URL da imagem deve ser permitida por img-src.

6. Verificar

  1. Carregue a página e assista a uma construção completa. Cada caixa deve cair em um bloco real de UI da imagem, não em espaço vazio ou cruzando dois blocos.
  2. Verifique uma largura de telefone (375px). Badges e tags de nome têm tamanho fixo, então imagens muito pequenas podem parecer cheias; use menos regiões maiores ali.
  3. Ative movimento reduzido no sistema operacional ou nas ferramentas de desenvolvedor do navegador: a imagem deve aparecer imediatamente, sem cursores.
  4. Verifique o console por erros e se nenhum elemento aria-hidden do enxame permanece no DOM após o término.

Habilidades Relacionadas