@xingwangzhe/tags-cloud: O Motor 3D Multi-Modal de Nuvem de Tags Baseado em Matemática Pura
@xingwangzhe/tags-cloud: O Motor 3D Multi-Modal de Nuvem de Tags Baseado em Matemática Pura
GitHub: xingwangzhe/tags-cloud · Demo: tagscloud.needhelp.icu · npm: @xingwangzhe/tags-cloud · Licença: MIT · Versão: v0.9.0
1. Introdução: Reinventando a Nuvem de Tags 3D para a Web Moderna
A nuvem de tags é um pilar da visualização web há mais de duas décadas, evoluindo de simples listas de palavras ponderadas para experiências tridimensionais imersivas que cativam usuários e transformam coleções de texto mundanas em esculturas espaciais interativas. Entre as contribuições mais influentes para essa evolução está o cong-min/TagCloud, uma biblioteca JavaScript leve que demonstrou como uma esfera de rótulos de texto rotativos poderia ser alcançada com sobrecarga mínima e zero dependências externas. Com 390 estrelas e 93 forks no GitHub, o TagCloud original estabeleceu um padrão de design que inúmeros desenvolvedores adotaram para portfólios, vitrines de habilidades e painéis de visualização de dados. Sua inovação central estava em provar que nuvens de tags 3D não precisam depender de frameworks WebGL pesados ou mecanismos de renderização externos; em vez disso, cálculos trigonométricos diretos combinados com posicionamento cuidadoso de DOM poderiam produzir resultados visuais surpreendentemente convincentes.
Apresentamos @xingwangzhe/tags-cloud — uma reinvenção completa do conceito de nuvem de tags 3D que preserva a elegância matemática de seu predecessor enquanto expande dramaticamente suas capacidades, moderniza sua arquitetura e empurra os limites do que uma nuvem de tags pode renderizar. Isto não é meramente um fork ou uma adição de funcionalidade; representa uma mudança arquitetural fundamental de um renderizador baseado apenas em texto e DOM para um motor multi-modal capaz de exibir texto, imagens, gráficos SVG, HTML arbitrário, elementos de vídeo e até Web Components completos — todos girando juntos em um espaço tridimensional matematicamente preciso. A biblioteca alcança essa versatilidade enquanto mantém uma pegada extraordinariamente compacta de aproximadamente 3KB gzipped, carrega zero dependências de runtime e é construída com um toolchain completamente moderno composto por Bun como runtime JavaScript, Vite como bundler e TypeScript para segurança total de tipos em toda a base de código.
O slogan do projeto — “nuvem de tags 3D multi-modal · motor de matemática pura” — encapsula sua identidade dupla. Por um lado, é um componente de UI prático que desenvolvedores podem inserir em qualquer projeto web para criar esferas de tags visualmente impressionantes. Por outro lado, é um motor matemático que decompõe o problema complexo da renderização de nuvens de tags 3D em três operações geométricas puras, determinísticas e lindamente separáveis: distribuição esférica de Fibonacci para posicionamento inicial, multiplicação de matrizes de rotação para transformação espacial e projeção perspectiva para renderização 2D com noção de profundidade. Cada uma dessas operações é implementada em seu próprio módulo dedicado dentro do diretório src/core/, tornando a base de código não apenas altamente mantível, mas também um excelente recurso educacional para qualquer um que queira entender a matemática por trás dos gráficos 3D computacionais sem a complexidade obscurecedora de um pipeline de renderização completo.
As seções a seguir fornecem um mergulho técnico abrangente em todos os aspectos do @xingwangzhe/tags-cloud, desde o algoritmo de distribuição esférica derivado da proporção áurea até o modelo de interação arcball inspirado em quatérnios, desde a arquitetura de renderização dupla Canvas/DOM até as considerações de design responsivo que o fazem funcionar perfeitamente em dispositivos desktop e móveis. Seja você um desenvolvedor avaliando esta biblioteca para seu próximo projeto, um programador gráfico interessado em técnicas 3D leves ou um matemático curioso sobre as aplicações reais do reticulado de Fibonacci, este artigo oferece explicações detalhadas, derivações matemáticas, diagramas arquiteturais e exemplos de código anotados para iluminar cada faceta desta notável peça de engenharia de software.
2. A Fundação Matemática: Três Pilares da Renderização 3D
No coração do @xingwangzhe/tags-cloud reside um trio de operações matemáticas que, quando compostas, transformam uma lista abstrata de itens de conteúdo em uma esfera rotativa visualmente coerente. Essas operações — distribuição, rotação e projeção — são implementadas em três módulos dedicados sob src/core/, cada um responsável por uma única transformação geométrica. Esta separação de preocupações não é meramente uma preferência arquitetural; ela reflete a estrutura fundamental dos pipelines de computação gráfica 3D, onde geração de vértices, transformação de modelo e projeção de câmera são estágios distintos que podem ser independentemente otimizados, testados e compreendidos.
flowchart LR
subgraph Input["📥 Camada de Entrada"]
TAGS["TagItem[]
(texto | imagem | SVG | HTML | vídeo | elemento)"]
OPTS["TagCloudOptions
(raio, spin, cores, callbacks)"]
end
subgraph CoreEngine["⚙️ Motor de Matemática Pura (src/core/)"]
direction TB
DIST["🔵 distribution.ts
Esfera de Fibonacci
N pontos → coordenadas 3D"]
ROT["🟢 rotation.ts
Matrizes de Rotação
pontos 3D → pontos 3D rotacionados"]
PROJ["🔴 projection.ts
Projeção Perspectiva
3D rotacionado → 2D + profundidade"]
end
subgraph RenderLayer["🎨 Camada de Renderização"]
direction TB
CANVAS["Canvas 2D API
(texto + imagens)"]
DOM["Sobreposição DOM
(SVG + HTML + vídeo + elementos)"]
end
subgraph Interaction["👤 Camada de Interação"]
MOUSE["Arrastar Mouse / Toque"]
INERTIA["Decaimento de Inércia
(0.96/frame)"]
end
TAGS --> DIST
OPTS --> DIST
DIST -->|"Vec3[]"| ROT
ROT -->|"Vec3[] Rotacionado"| PROJ
PROJ -->|"ProjectedTag[]
(x, y, z, escala, alpha)"| CANVAS
PROJ --> DOM
MOUSE --> INERTIA
INERTIA -->|"ângulos de rotação"| ROT
style CoreEngine fill:#1a1a2e,stroke:#16213e
style Input fill:#0f3460,stroke:#16213e
style RenderLayer fill:#533483,stroke:#16213e
style Interaction fill:#e94560,stroke:#16213e,color:#fff
2.1 Distribuição Esférica de Fibonacci: A Geometria Dourada do Posicionamento de Pontos
O primeiro passo — e indiscutivelmente o mais crítico esteticamente — na criação de uma nuvem de tags 3D é determinar onde cada tag deve ser posicionada na esfera. Uma abordagem ingênua colocaria as tags em intervalos regulares de latitude e longitude, mas isso inevitavelmente leva ao agrupamento nos polos, onde as linhas meridionais convergem, e regiões esparsas perto do equador. O algoritmo da esfera de Fibonacci resolve este problema elegantemente ao produzir uma distribuição de pontos que é notavelmente uniforme em toda a superfície da esfera, sem agrupamento visível ou lacunas, independentemente do número de pontos.
Este algoritmo deve seu nome à proporção áurea (\varphi = \frac{1 + \sqrt{5}}{2} \approx 1.6180339887), uma constante matemática que aparece em toda a natureza, desde arranjos de sementes de girassol até espirais de conchas de nautilus. A conexão com os números de Fibonacci — a sequência onde cada termo é a soma dos dois anteriores — é que a razão de números consecutivos de Fibonacci converge para a proporção áurea conforme a sequência progride. No contexto da distribuição esférica, a irracionalidade da proporção áurea garante que pontos sucessivos sejam sempre colocados em ângulos que nunca se repetem, criando um padrão espiral aperiódico que preenche a superfície da esfera uniformemente.
A implementação específica em src/core/distribution.ts usa uma variação do reticulado de Fibonacci que foi otimizada para mapeamento esférico. Para uma esfera de raio (R) com (N) pontos a distribuir, o algoritmo calcula as coordenadas esféricas e depois as converte para coordenadas cartesianas ((x, y, z)) para cada ponto (i \in {0, 1, 2, \ldots, N-1}). O ângulo de latitude (\phi) (medido a partir do eixo z positivo, ou seja, o polo Norte) é calculado usando a função arco cosseno para garantir distribuição uniforme ao longo do eixo z:
Esta fórmula coloca o primeiro ponto ligeiramente abaixo do polo Norte e o último ponto ligeiramente acima do polo Sul, com o deslocamento (+0.5) (embutido no numerador (2i + 1)) garantindo que nenhum ponto caia exatamente em um polo. Este ajuste sutil é crucial porque previne o artefato visual de uma tag sentada diretamente no topo ou fundo da esfera, onde a rotação seria quase imperceptível. A função (\arccos) transforma um parâmetro linear uniformemente distribuído em uma distribuição angular ponderada por cosseno, o que compensa o fato de que esferas têm menos área de superfície perto dos polos e mais perto do equador.
O ângulo de longitude (\theta) (medido no plano xy a partir do eixo x positivo) é calculado usando uma escala de (\phi) por (\sqrt{N\pi}), o que cria o padrão espiral característico:
O fator (\sqrt{N\pi}) é derivado da relação entre o ângulo dourado e a área total da superfície da esfera. À medida que (N) aumenta, esta escala garante que a espiral envolva a esfera o número apropriado de vezes para manter o espaçamento uniforme entre pontos vizinhos. O resultado é um padrão onde cada ponto sucessivo é rotacionado em aproximadamente o ângulo dourado (\approx 137.5°) em relação ao seu predecessor quando visto ao longo do eixo z, espelhando as espirais filotáticas encontradas na natureza.
Finalmente, estas coordenadas esféricas são convertidas para coordenadas cartesianas usando a transformação padrão:
Os pontos resultantes satisfazem a equação da esfera (x_i^2 + y_i^2 + z_i^2 = R^2) e são distribuídos com uma uniformidade que rivaliza com métodos baseados em otimização muito mais caros computacionalmente. A exibição a seguir resume o algoritmo completo da esfera de Fibonacci:
A implementação em TypeScript em src/core/distribution.ts é notavelmente concisa, refletindo a simplicidade elegante do algoritmo:
export interface Vec3 { x: number; y: number; z: number; }
export function fibonacciSphere(n: number, R: number): Vec3[] { const points: Vec3[] = []; for (let i = 0; i < n; i++) { const phi = Math.acos(-1 + (2 * i + 1) / n); const theta = Math.sqrt(n * Math.PI) * phi; points.push({ x: R * Math.cos(theta) * Math.sin(phi), y: R * Math.sin(theta) * Math.sin(phi), z: R * Math.cos(phi), }); } return points;}Esta função retorna um array de objetos Vec3 que servem como posições iniciais para todas as tags na nuvem. O algoritmo executa em tempo (\mathcal{O}(N)), tornando-o adequado para nuvens de tags com centenas de elementos. Na prática, a maioria das nuvens de tags contém entre 20 e 100 tags, para as quais este cálculo é virtualmente instantâneo.
2.2 Rotação 3D: Multiplicação de Matrizes no Domínio Espacial
Uma vez que as tags estão posicionadas na superfície da esfera, o próximo passo é permitir a rotação — tanto o giro automático contínuo quanto a interação de arrasto iniciada pelo usuário. A biblioteca implementa rotação usando matrizes de rotação compostas alinhadas aos eixos, especificamente rotações sequenciais em torno do eixo Y seguidas pelo eixo X. Esta abordagem é computacionalmente eficiente, fácil de entender e totalmente suficiente para o caso de uso da nuvem de tags, onde rotações são sempre relativas a uma esfera centrada na origem.
A base matemática para estas rotações vem da álgebra linear. Uma matriz de rotação 3D é uma matriz ortogonal (3 \times 3) com determinante 1 que transforma as coordenadas de um ponto enquanto preserva sua distância da origem. Para rotação por um ângulo (\alpha) em torno do eixo Y, a matriz de rotação (R_y(\alpha)) é:
Para rotação por um ângulo (\beta) em torno do eixo X, a matriz de rotação (R_x(\beta)) é:
A biblioteca aplica estas rotações sequencialmente: primeiro a rotação no eixo Y, depois a rotação no eixo X. Para um ponto (P = (x, y, z)), a rotação no eixo Y produz um ponto intermediário (P’):
A rotação no eixo X é então aplicada a (P’) para produzir o ponto final rotacionado (P’’):
A implementação em src/core/rotation.ts expande estas multiplicações de matrizes em operações aritméticas diretas, evitando a sobrecarga de alocação e multiplicação de objetos de matriz. Para um único ponto, a função de rotação computa:
A função rotatePoints realiza esta transformação em lote para todas as tags:
export function rotatePoints(points: Vec3[], a: number, b: number): Vec3[] { const sinA = Math.sin(a), cosA = Math.cos(a); const sinB = Math.sin(b), cosB = Math.cos(b); return points.map((p) => { const y1 = p.y * cosA + p.z * -sinA; const z1 = p.y * sinA + p.z * cosA; const x2 = p.x * cosB + z1 * sinB; return { x: x2, y: y1, z: z1 * cosB - p.x * sinB }; });}2.3 Projeção Perspectiva: Do Espaço 3D para a Tela 2D
A operação matemática final transforma as coordenadas 3D rotacionadas em posições 2D na tela. A biblioteca usa um modelo de projeção simplificado, mas altamente eficaz, que calcula um fator de escala e um fator de opacidade baseados na profundidade, com um parâmetro de profundidade de perspectiva igual ao dobro do raio da esfera:
A opacidade (alfa) usa uma relação quadrática com ajuste de viés:
O pipeline completo de projeção é resumido como:
A implementação em TypeScript espelha esta matemática precisamente:
export function project( points: { x: number; y: number; z: number }[], depth: number,): ProjectedTag[] { const d2 = 2 * depth; return points.map((p) => { const per = d2 / (d2 + p.z); const alpha = Math.min(1, Math.max(0, per * per - 0.25)); return { x: p.x, y: p.y, z: p.z, scale: per, alpha }; });}3. Arquitetura e Design de Módulos
A base de código exemplifica arquitetura de software limpa através da separação deliberada entre computação matemática, orquestração de renderização e tratamento de interação do usuário.
3.1 O Motor de Matemática Pura: src/core/
| Módulo | Função | Entrada | Saída | Fórmula Chave |
|---|---|---|---|---|
| distribution.ts | fibonacciSphere(n, R) | N, R | Vec3[] | (\phi_i = \arccos(-1 + \frac{2i+1}{N})) |
| rotation.ts | rotatePoints(points, a, b) | Vec3[], a, b | Vec3[] | (R_y(a)) · (R_x(b)) · (P) |
| projection.ts | project(points, depth) | Vec3[], d | ProjectedTag[] | per = 2d/(2d+z), (\alpha) = per(^2) - 0.25 |
3.2 O Sistema de Renderização Dupla: Canvas + DOM
Uma das inovações mais significativas é seu sistema de renderização dupla, usando a Canvas 2D API para texto e imagens, e sobreposição DOM para SVG, HTML, vídeo e Web Components.
flowchart TB
subgraph "Tipos de Tag & Renderizadores"
direction LR
TEXT["📄 Tag de Texto"]
IMG["🖼️ Tag de Imagem"]
SVG_TAG["🎨 Tag SVG"]
HTML_TAG["🌐 Tag HTML"]
VIDEO["🎬 Tag de Vídeo"]
ELEMENT["🔧 Tag de Elemento"]
end
subgraph "Seleção de Renderizador"
CANVAS["Canvas 2D API
✅ Texto
✅ Imagens"]
DOM["Sobreposição DOM
✅ SVG
✅ HTML
✅ Vídeo
✅ Web Components"]
end
TEXT --> CANVAS
IMG --> CANVAS
SVG_TAG --> DOM
HTML_TAG --> DOM
VIDEO --> DOM
ELEMENT --> DOM
style CANVAS fill:#0f3460,stroke:#e94560,color:#fff
style DOM fill:#533483,stroke:#e94560,color:#fff
4. Características de Performance
4.1 Complexidade Computacional
| Estágio | Complexidade | Operações Dominantes |
|---|---|---|
| Rotação | O(N) | 8 muls + 4 adds por ponto |
| Projeção | O(N) | 1 div + 2 muls + 1 add por ponto |
| Z-sort | O(N log N) | Ordenação por comparação |
| Renderização Canvas | O(N) | Chamadas fillText / drawImage |
| Atualização DOM | O(N) | Definição de transform + opacity |
4.2 Eficiência de Memória
Para (N = 100) tags, o estado numérico total é cerca de (100 \times (3 + 5) \times 8 = 6.400) bytes — menos de 7KB de números de ponto flutuante.
4.3 Tamanho do Bundle
| Formato | Tamanho |
|---|---|
| ESM (dist/index.js) | ~12 KB |
| Gzip | ~3 KB |
| Brotli | ~2.5 KB |
5. Conteúdo Multi-Modal: Seis Tipos de Tag
| Tipo de Tag | Formato de Entrada | Renderizador | Interatividade | Caso de Uso |
|---|---|---|---|---|
| Texto | string | Canvas 2D | callback onTagClick | Habilidades, palavras-chave |
| Imagem | { type:“image”, src, w, h } | Canvas 2D | onClick por tag | Logos, avatares |
| SVG | { type:“svg”, content, w, h } | DOM | onClick por tag | Ícones vetoriais |
| HTML | { type:“html”, html } | DOM | onClick por tag | Texto formatado rico |
| Vídeo | { type:“video”, src, w, h } | DOM | Tela cheia ao clicar | Clipes de demonstração |
| Elemento | { type:“element”, element } | DOM | Eventos DOM nativos | Web Components |
6. Comparação com cong-min/TagCloud
| Aspecto | cong-min/TagCloud | @xingwangzhe/tags-cloud | Melhoria |
|---|---|---|---|
| Linguagem | JavaScript (ES5) | TypeScript | Segurança total de tipos |
| Tamanho do Bundle | ~6KB minificado | ~3KB gzipped | ~50% menor |
| Dependências | 0 | 0 | Ambos sem dependências |
| Tipos de Tag | Apenas texto | Texto, Imagem, SVG, HTML, Vídeo, Elemento | 6x modalidades de conteúdo |
| Renderizador | Apenas DOM | Canvas 2D + DOM híbrido | Performance superior |
| Ferramenta de Build | Rollup + Babel | Vite + Bun + Oxlint | Toolchain moderno |
| Interação de Arrasto | Arrasto básico de mouse | Estilo arcball + inércia | Sensação mais natural |
| Suporte a Toque | Não explícito | Toque completo + CSS mobile | Pronto para mobile |
7. Guia Prático de Uso
7.1 Nuvem Básica Apenas com Texto
import { TagCloud } from "@xingwangzhe/tags-cloud";
const container = document.getElementById("cloud")!;new TagCloud(container, { tags: ["TypeScript", "React", "Vue", "Svelte", "Node.js", "Bun", "Rust"], radius: 250, spinY: 0.12, color: "#e0e0e0", fontSize: 16,});7.2 Nuvem Multi-Modal
new TagCloud(container, { tags: [ "TypeScript", { type: "image", src: "/avatar.webp", width: 40, height: 40 }, { type: "svg", content: `<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/></svg>`, width: 48, height: 48 }, { type: "video", src: "/demo.mp4", width: 120, height: 68 }, ], radius: 300, spinY: 0.15, onTagClick(item) { console.log("Clicked:", item); },});7.3 Gerenciamento do Ciclo de Vida
const cloud = new TagCloud(container, { tags, spinY: 0.2 });cloud.setTags(["New", "Set", "Of", "Tags"]);cloud.pause();cloud.resume();cloud.destroy();8. Conclusão: A Matemática como Motor de Renderização
@xingwangzhe/tags-cloud se destaca como uma demonstração convincente de que o motor de renderização mais poderoso no software não é uma GPU, um compilador de shader ou um framework — é a matemática. Ao decompor o problema da visualização de nuvens de tags 3D em três operações matemáticas puras — distribuição esférica de Fibonacci, multiplicação de matrizes de rotação e projeção perspectiva — a biblioteca alcança resultados que são visualmente indistinguíveis de alternativas baseadas em WebGL, sem exigir nenhuma de sua complexidade, dependências de hardware ou peso de bundle.
As contribuições do projeto para o ecossistema de código aberto são triplas. Arquiteturalmente, prova que um renderizador híbrido Canvas/DOM pode entregar tanto performance quanto versatilidade dentro de um pacote de 3KB. Matematicamente, fornece implementações limpas e bem documentadas de algoritmos fundamentais de gráficos 3D. Na prática, oferece aos desenvolvedores um componente plug-and-play para criar nuvens de tags 3D com suporte a mídia rica, segurança de tipos TypeScript e interação pronta para mobile — tudo sem adicionar uma única dependência.
Fim do Artigo — Baseado na análise do código-fonte do @xingwangzhe/tags-cloud v0.9.0