needhelp
← Volver al blog

@xingwangzhe/tags-cloud: El Motor de Nube de Etiquetas 3D Multi-Modal Construido sobre Matemáticas Puras

por needhelp
TagsCloud
3D
TypeScript
Math
Visualization
Open Source

@xingwangzhe/tags-cloud: El Motor de Nube de Etiquetas 3D Multi-Modal Construido sobre Matemáticas Puras

GitHub: xingwangzhe/tags-cloud · Demo: tagscloud.needhelp.icu · npm: @xingwangzhe/tags-cloud · Licencia: MIT · Versión: v0.9.0


1. Introducción: Reimaginando la Nube de Etiquetas 3D para la Web Moderna

La nube de etiquetas ha sido un elemento básico de la visualización web durante más de dos décadas, evolucionando desde simples listas de palabras ponderadas hasta experiencias tridimensionales inmersivas que cautivan a los usuarios y transforman colecciones de texto mundanas en esculturas espaciales interactivas. Entre las contribuciones más influyentes a esta evolución se encuentra cong-min/TagCloud, una librería JavaScript ligera que demostró cómo se podía lograr una esfera de etiquetas de texto rotativas con un costo mínimo y cero dependencias externas. Con 390 estrellas y 93 forks en GitHub, el TagCloud original estableció un patrón de diseño que innumerables desarrolladores han adoptado para sitios de portafolio, vitrinas de habilidades y paneles de visualización de datos. Su innovación central consistió en demostrar que las nubes de etiquetas 3D no necesitan depender de frameworks WebGL pesados ni motores de renderizado externos; en cambio, cálculos trigonométricos directos combinados con un cuidadoso posicionamiento DOM podían producir resultados visuales sorprendentemente convincentes.

Presentamos @xingwangzhe/tags-cloud — una reinvención desde cero del concepto de nube de etiquetas 3D que preserva la elegancia matemática de su predecesor mientras expande drásticamente sus capacidades, moderniza su arquitectura y empuja los límites de lo que una nube de etiquetas puede renderizar. Esto no es meramente un fork o una adición de funcionalidades; representa un cambio arquitectónico fundamental de un renderizador de solo texto y con mucho DOM a un motor multi-modal capaz de mostrar texto, imágenes, gráficos SVG, HTML arbitrario, elementos de video e incluso Web Components completos — todos rotando juntos en un espacio tridimensional matemáticamente preciso. La librería logra esta versatilidad mientras mantiene una huella extraordinariamente compacta de aproximadamente 3KB comprimido con gzip, sin dependencias en tiempo de ejecución, y construida con una toolchain completamente moderna que comprende Bun como runtime JavaScript, Vite como bundler y TypeScript para seguridad de tipos completa en toda la base de código.

El eslogan del proyecto — “nube de etiquetas 3D multi-modal · motor de matemáticas puras” — encapsula su doble identidad. Por un lado, es una librería de componentes UI práctica que los desarrolladores pueden integrar en cualquier proyecto web para crear esferas de etiquetas visualmente impactantes. Por otro lado, es un motor matemático que descompone el complejo problema del renderizado de nubes de etiquetas 3D en tres operaciones geométricas puras, deterministas y hermosamente separables: distribución de esfera de Fibonacci para el posicionamiento inicial, multiplicación de matrices de rotación para la transformación espacial y proyección perspectiva para el renderizado 2D consciente de profundidad. Cada una de estas operaciones está implementada en su propio módulo dedicado dentro del directorio src/core/, haciendo que la base de código no solo sea altamente mantenible sino también un excelente recurso educativo para cualquiera que busque entender las matemáticas detrás de los gráficos 3D por computadora sin la complejidad oscurecedora de un pipeline de renderizado completo.

Las siguientes secciones proporcionan una inmersión técnica exhaustiva en cada aspecto de @xingwangzhe/tags-cloud, desde el algoritmo de distribución de esfera derivado de la proporción áurea hasta el modelo de interacción arcball inspirado en cuaterniones, desde la arquitectura de renderizado dual Canvas/DOM hasta las consideraciones de diseño responsivo que lo hacen funcionar sin problemas en dispositivos de escritorio y móviles. Ya seas un desarrollador evaluando esta librería para tu próximo proyecto, un programador de gráficos interesado en técnicas 3D ligeras, o un matemático curioso sobre las aplicaciones del mundo real de la red de Fibonacci, este artículo ofrece explicaciones detalladas, derivaciones matemáticas, diagramas arquitectónicos y ejemplos de código anotados para iluminar cada faceta de esta notable pieza de ingeniería de software.


2. El Fundamento Matemático: Tres Pilares del Renderizado 3D

En el corazón de @xingwangzhe/tags-cloud yace un trío de operaciones matemáticas que, al componerse, transforman una lista abstracta de elementos de contenido en una esfera rotatoria visualmente coherente. Estas operaciones — distribución, rotación y proyección — están implementadas en tres módulos dedicados bajo src/core/, cada uno responsable de una única transformación geométrica. Esta separación de responsabilidades no es meramente una preferencia arquitectónica; refleja la estructura fundamental de los pipelines de gráficos 3D por computadora, donde la generación de vértices, la transformación del modelo y la proyección de cámara son etapas distintas que pueden optimizarse, probarse y entenderse de forma independiente.

flowchart LR
    subgraph Input["📥 Capa de Entrada"]
        TAGS["TagItem[]
(text | image | SVG | HTML | video | element)"] OPTS["TagCloudOptions
(radius, spin, colors, callbacks)"] end subgraph CoreEngine["⚙️ Motor de Matemáticas Puras (src/core/)"] direction TB DIST["🔵 distribution.ts
Esfera de Fibonacci
N puntos → coordenadas 3D"] ROT["🟢 rotation.ts
Matrices de Rotación
puntos 3D → puntos 3D rotados"] PROJ["🔴 projection.ts
Proyección Perspectiva
3D rotado → 2D + profundidad"] end subgraph RenderLayer["🎨 Capa de Renderizado"] direction TB CANVAS["Canvas 2D API
(texto + imágenes)"] DOM["Superposición DOM
(SVG + HTML + video + elementos)"] end subgraph Interaction["👤 Capa de Interacción"] MOUSE["Arrastre de Mouse / Táctil"] INERTIA["Decaimiento de Inercia
(0.96/frame)"] end TAGS --> DIST OPTS --> DIST DIST -->|"Vec3[]"| ROT ROT -->|"Vec3[] rotados"| PROJ PROJ -->|"ProjectedTag[]
(x, y, z, scale, alpha)"| CANVAS PROJ --> DOM MOUSE --> INERTIA INERTIA -->|"ángulos de rotación"| 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 Distribución de Esfera de Fibonacci: La Geometría Áurea del Posicionamiento de Puntos

El primer paso, y probablemente el más crítico desde el punto de vista estético, para crear una nube de etiquetas 3D es determinar dónde debe colocarse cada etiqueta en la esfera. Un enfoque ingenuo podría colocar etiquetas en intervalos regulares de latitud y longitud, pero esto inevitablemente lleva a agrupaciones en los polos, donde convergen las líneas de meridiano, y regiones dispersas cerca del ecuador. El algoritmo de esfera de Fibonacci resuelve este problema elegantemente produciendo una distribución de puntos notablemente uniforme en toda la superficie de la esfera, sin agrupaciones ni espacios visibles independientemente del número de puntos.

Este algoritmo toma su nombre de la proporción áurea (\varphi = \frac{1 + \sqrt{5}}{2} \approx 1.6180339887), una constante matemática que aparece en toda la naturaleza en estructuras que van desde la disposición de semillas de girasol hasta las espirales de conchas de nautilus. La conexión con los números de Fibonacci — la secuencia donde cada término es la suma de los dos anteriores — es que la proporción de números de Fibonacci consecutivos converge a la proporción áurea a medida que la secuencia progresa. En el contexto de la distribución en una esfera, la irracionalidad de la proporción áurea asegura que los puntos sucesivos siempre se colocan en ángulos que nunca se repiten, creando un patrón espiral aperiódico que llena la superficie de la esfera de manera uniforme.

La implementación específica en src/core/distribution.ts usa una variación de la red de Fibonacci que ha sido optimizada para mapeo esférico. Para una esfera de radio (R) con (N) puntos a distribuir, el algoritmo calcula las coordenadas esféricas y luego las convierte a coordenadas cartesianas ((x, y, z)) para cada punto (i \in {0, 1, 2, \ldots, N-1}). El ángulo de latitud (\phi) (medido desde el eje z positivo, es decir, el polo Norte) se calcula usando la función arcocoseno para asegurar una distribución uniforme a lo largo del eje z:

ϕi=arccos(1+2i+1N)\phi_i = \arccos\left(-1 + \frac{‘{’}2i + 1{‘}’}{‘{’}N{‘}’}\right)

Esta fórmula coloca el primer punto ligeramente debajo del polo Norte y el último punto ligeramente arriba del polo Sur, con el desplazamiento (+0.5) (incorporado en el numerador (2i + 1)) asegurando que ningún punto caiga exactamente sobre un polo. Este ajuste sutil es crucial porque previene el artefacto visual de una etiqueta situada directamente en la parte superior o inferior de la esfera donde la rotación sería apenas perceptible. La función (\arccos) transforma un parámetro lineal distribuido uniformemente en una distribución angular ponderada por coseno, lo que compensa el hecho de que las esferas tienen menos área superficial cerca de los polos y más cerca del ecuador.

El ángulo de longitud (\theta) (medido en el plano xy desde el eje x positivo) se calcula usando un escalado de (\phi) por (\sqrt{N\pi}), lo que crea el patrón espiral característico:

θi=Nπϕi\theta_i = \sqrt{‘{’}N\pi{‘}’} \cdot \phi_i

El factor (\sqrt{N\pi}) se deriva de la relación entre el ángulo áureo y el área superficial total de la esfera. A medida que (N) aumenta, este escalado asegura que la espiral se enrolle alrededor de la esfera el número apropiado de veces para mantener un espaciado uniforme entre puntos vecinos. El resultado es un patrón donde cada punto sucesivo está rotado aproximadamente por el ángulo áureo (\approx 137.5°) en relación con su predecesor cuando se ve a lo largo del eje z, reflejando las espirales filotácticas encontradas en la naturaleza.

Finalmente, estas coordenadas esféricas se convierten a coordenadas cartesianas usando la transformación estándar:

xi=Rcos(θi)sin(ϕi)x_i = R \cdot \cos(\theta_i) \cdot \sin(\phi_i)

yi=Rsin(θi)sin(ϕi)y_i = R \cdot \sin(\theta_i) \cdot \sin(\phi_i)

zi=Rcos(ϕi)z_i = R \cdot \cos(\phi_i)

Los puntos resultantes satisfacen la ecuación de la esfera (x_i^2 + y_i^2 + z_i^2 = R^2) y se distribuyen con una uniformidad que rivaliza con métodos basados en optimización mucho más costosos computacionalmente. El siguiente recuadro resume el algoritmo completo de la esfera de Fibonacci:

FibonacciSphere(N,R):i[0,N1]:{‘{’}ϕi=arccos(1+2i+1N)θi=NπϕiPi=(Rsinϕicosθi,  Rsinϕisinθi,  Rcosϕi)\boxed{‘{’}\text{‘{’}FibonacciSphere{‘}’}(N, R): \quad \forall i \in [0, N-1]: \begin{‘{’}cases{‘}’} \phi_i = \arccos\left(-1 + \frac{‘{’}2i+1{‘}’}{‘{’}N{‘}’}\right) \ \theta_i = \sqrt{‘{’}N\pi{‘}’} \cdot \phi_i \ P_i = (R\sin\phi_i\cos\theta_i, ; R\sin\phi_i\sin\theta_i, ; R\cos\phi_i) \end{‘{’}cases{‘}’}{‘}’}

La implementación en TypeScript en src/core/distribution.ts es notablemente concisa, reflejando la elegante simplicidad del 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 función devuelve un array de objetos Vec3 que sirven como las posiciones iniciales para todas las etiquetas en la nube. El algoritmo se ejecuta en tiempo (\mathcal{O}(N)), lo que lo hace adecuado para nubes de etiquetas con cientos de elementos. En la práctica, la mayoría de las nubes de etiquetas contienen entre 20 y 100 etiquetas, para las cuales este cálculo es virtualmente instantáneo.

2.2 Rotación 3D: Multiplicación de Matrices en el Dominio Espacial

Una vez que las etiquetas están posicionadas en la superficie de la esfera, el siguiente paso es permitir la rotación — tanto el giro automático continuo como la interacción de arrastre por parte del usuario. La librería implementa la rotación usando matrices de rotación compuestas alineadas a los ejes, específicamente rotaciones secuenciales alrededor del eje Y seguidas del eje X. Este enfoque es computacionalmente eficiente, fácil de entender y completamente suficiente para el caso de uso de nubes de etiquetas donde las rotaciones siempre son relativas a una esfera centrada en el origen.

El fundamento matemático para estas rotaciones proviene del álgebra lineal. Una matriz de rotación 3D es una matriz ortogonal (3 \times 3) con determinante 1 que transforma las coordenadas de un punto mientras preserva su distancia al origen. Para la rotación por un ángulo (\alpha) alrededor del eje Y, la matriz de rotación (R_y(\alpha)) es:

Ry(α)=(cosα0sinα010sinα0cosα)R_y(\alpha) = \begin{‘{’}pmatrix{‘}’} \cos\alpha & 0 & \sin\alpha \ 0 & 1 & 0 \ -\sin\alpha & 0 & \cos\alpha \end{‘{’}pmatrix{‘}’}

Para la rotación por un ángulo (\beta) alrededor del eje X, la matriz de rotación (R_x(\beta)) es:

Rx(β)=(1000cosβsinβ0sinβcosβ)R_x(\beta) = \begin{‘{’}pmatrix{‘}’} 1 & 0 & 0 \ 0 & \cos\beta & -\sin\beta \ 0 & \sin\beta & \cos\beta \end{‘{’}pmatrix{‘}’}

La librería aplica estas rotaciones secuencialmente: primero la rotación alrededor del eje Y, luego la rotación alrededor del eje X. Para un punto (P = (x, y, z)), la rotación alrededor del eje Y produce un punto intermedio (P’):

(xyz)=Ry(α)(xyz)=(xcosα+zsinαyxsinα+zcosα)\begin{‘{’}pmatrix{‘}’} x' \ y' \ z' \end{‘{’}pmatrix{‘}’} = R_y(\alpha) \begin{‘{’}pmatrix{‘}’} x \ y \ z \end{‘{’}pmatrix{‘}’} = \begin{‘{’}pmatrix{‘}’} x\cos\alpha + z\sin\alpha \ y \ -x\sin\alpha + z\cos\alpha \end{‘{’}pmatrix{‘}’}

Luego se aplica la rotación alrededor del eje X a (P’) para producir el punto rotado final (P’’):

(xyz)=Rx(β)(xyz)=(xycosβzsinβysinβ+zcosβ)\begin{‘{’}pmatrix{‘}’} x'' \ y'' \ z'' \end{‘{’}pmatrix{‘}’} = R_x(\beta) \begin{‘{’}pmatrix{‘}’} x' \ y' \ z' \end{‘{’}pmatrix{‘}’} = \begin{‘{’}pmatrix{‘}’} x' \ y'\cos\beta - z'\sin\beta \ y'\sin\beta + z'\cos\beta \end{‘{’}pmatrix{‘}’}

La implementación en src/core/rotation.ts expande estas multiplicaciones de matrices en operaciones aritméticas directas, evitando la sobrecarga de la asignación y multiplicación de objetos matriz. Para un solo punto, la función de rotación calcula:

y1=ycosα+z(sinα)z1=ysinα+zcosαx2=xcosβ+z1sinβz2=z1cosβxsinβP=(x2,  y1,  z2)\boxed{‘{’}\begin{‘{’}aligned{‘}’} y_1 &= y \cdot \cos\alpha + z \cdot (-\sin\alpha) \ z_1 &= y \cdot \sin\alpha + z \cdot \cos\alpha \ x_2 &= x \cdot \cos\beta + z_1 \cdot \sin\beta \ z_2 &= z_1 \cdot \cos\beta - x \cdot \sin\beta \ P'' &= (x_2, ; y_1, ; z_2) \end{‘{’}aligned{‘}’}{‘}’}

La función rotatePoints realiza esta transformación en lote para todas las etiquetas:

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 Proyección Perspectiva: Del Espacio 3D a la Pantalla 2D

La operación matemática final transforma las coordenadas 3D rotadas en posiciones de pantalla 2D. La librería usa un modelo de proyección simplificado pero altamente efectivo que calcula un factor de escala y un factor de opacidad basados en la profundidad, con un parámetro de profundidad de perspectiva igual al doble del radio de la esfera:

per=2depth2depth+z=4R4R+z\text{‘{’}per{‘}’} = \frac{‘{’}2 \cdot \text{‘{’}depth{‘}’}{‘}’}{‘{’}2 \cdot \text{‘{’}depth{‘}’} + z{‘}’} = \frac{‘{’}4R{‘}’}{‘{’}4R + z{‘}’}

El factor de opacidad (alpha) usa una relación cuadrática con un ajuste de sesgo:

alpha=clamp(per20.25,  0,  1)\text{‘{’}alpha{‘}’} = \text{‘{’}clamp{‘}’}\left(\text{‘{’}per{‘}’}^2 - 0.25, ; 0, ; 1\right)

El pipeline de proyección completo se resume como:

peri=2depth2depth+ziscalei=perialphai=min(1,  max(0,  peri20.25))Pi2D=(xiscalei,  yiscalei,  scalei,  alphai)\boxed{‘{’}\begin{‘{’}aligned{‘}’} \text{‘{’}per{‘}’}_i &= \frac{‘{’}2 \cdot \text{‘{’}depth{‘}’}{‘}’}{‘{’}2 \cdot \text{‘{’}depth{‘}’} + z_i{‘}’} \ \text{‘{’}scale{‘}’}_i &= \text{‘{’}per{‘}’}_i \ \text{‘{’}alpha{‘}’}_i &= \min\left(1, ; \max\left(0, ; \text{‘{’}per{‘}’}_i^2 - 0.25\right)\right) \ P_i^{‘{’}\text{‘{’}2D{‘}’}{‘}’} &= \left(x_i \cdot \text{‘{’}scale{‘}’}_i, ; y_i \cdot \text{‘{’}scale{‘}’}_i, ; \text{‘{’}scale{‘}’}_i, ; \text{‘{’}alpha{‘}’}_i\right) \end{‘{’}aligned{‘}’}{‘}’}

La implementación en TypeScript refleja estas matemáticas con precisión:

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. Arquitectura y Diseño de Módulos

La base de código ejemplifica una arquitectura de software limpia mediante la separación deliberada del cálculo matemático, la orquestación del renderizado y el manejo de la interacción del usuario.

3.1 El Motor de Matemáticas Puras: src/core/

Módulo Función Entrada Salida Fórmula Clave
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 El Sistema de Renderizado Dual: Canvas + DOM

Una de las innovaciones más significativas es su sistema de renderizado dual, que usa la API Canvas 2D para texto e imágenes, y una superposición DOM para SVG, HTML, video y Web Components.

flowchart TB
    subgraph "Tipos de Etiqueta y Renderizadores"
        direction LR
        TEXT["📄 Etiqueta de Texto"]
        IMG["🖼️ Etiqueta de Imagen"]
        SVG_TAG["🎨 Etiqueta SVG"]
        HTML_TAG["🌐 Etiqueta HTML"]
        VIDEO["🎬 Etiqueta de Video"]
        ELEMENT["🔧 Etiqueta de Elemento"]
    end

    subgraph "Selección de Renderizador"
        CANVAS["Canvas 2D API
✅ Texto
✅ Imágenes"] DOM["Superposición DOM
✅ SVG
✅ HTML
✅ Video
✅ 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 Rendimiento

4.1 Complejidad Computacional

Etapa Complejidad Operaciones Dominantes
Rotación O(N) 8 mul + 4 sum por punto
Proyección O(N) 1 div + 2 mul + 1 sum por punto
Z-sort O(N log N) Ordenamiento por comparación
Renderizado Canvas O(N) Llamadas fillText / drawImage
Actualización DOM O(N) transform + opacity set

4.2 Eficiencia de Memoria

Para (N = 100) etiquetas, el estado numérico total es de aproximadamente (100 \times (3 + 5) \times 8 = 6,400) bytes — menos de 7KB de números de punto flotante.

4.3 Tamaño del Bundle

Formato Tamaño
ESM (dist/index.js) ~12 KB
Gzip ~3 KB
Brotli ~2.5 KB

5. Contenido Multi-Modal: Seis Tipos de Etiqueta

Tipo de Etiqueta Formato de Entrada Renderizador Interactividad Caso de Uso
Texto string Canvas 2D callback onTagClick Habilidades, palabras clave
Imagen { type:“image”, src, w, h } Canvas 2D onClick por etiqueta Logos, avatares
SVG { type:“svg”, content, w, h } DOM onClick por etiqueta Iconos vectoriales
HTML { type:“html”, html } DOM onClick por etiqueta Texto con formato enriquecido
Video { type:“video”, src, w, h } DOM Pantalla completa al hacer clic Clips de demostración
Elemento { type:“element”, element } DOM Eventos DOM nativos Web Components

6. Comparación con cong-min/TagCloud

Aspecto cong-min/TagCloud @xingwangzhe/tags-cloud Mejora
Lenguaje JavaScript (ES5) TypeScript Seguridad de tipos completa
Tamaño del Bundle ~6KB minificado ~3KB comprimido con gzip ~50% más pequeño
Dependencias 0 0 Ambos sin dependencias
Tipos de Etiqueta Solo texto Texto, Imagen, SVG, HTML, Video, Elemento 6x modalidades de contenido
Renderizador Solo DOM Canvas 2D + DOM híbrido Mejor rendimiento
Herramienta de Build Rollup + Babel Vite + Bun + Oxlint Toolchain moderna
Interacción de Arrastre Arrastre básico con mouse Estilo arcball + inercia Sensación más natural
Soporte Táctil No explícito Táctil completo + CSS móvil Listo para móviles

7. Guía de Uso Práctica

7.1 Nube Básica de Solo 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 Nube 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 Gestión del 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. Conclusión: Las Matemáticas como Motor de Renderizado

@xingwangzhe/tags-cloud se presenta como una demostración convincente de que el motor de renderizado más poderoso en el software no es una GPU, un compilador de shaders o un framework — son las matemáticas. Al descomponer el problema de la visualización de nubes de etiquetas 3D en tres operaciones matemáticas puras — distribución de esfera de Fibonacci, multiplicación de matrices de rotación y proyección perspectiva — la librería logra resultados visualmente indistinguibles de alternativas basadas en WebGL sin requerir ninguna de sus complejidades, dependencias de hardware o peso de bundle.

Las contribuciones del proyecto al ecosistema de código abierto son triples. Arquitectónicamente, demuestra que un renderizador híbrido Canvas/DOM puede ofrecer tanto rendimiento como versatilidad dentro de un paquete de 3KB. Matemáticamente, proporciona implementaciones limpias y bien documentadas de algoritmos fundamentales de gráficos 3D. Prácticamente, ofrece a los desarrolladores un componente listo para usar para crear nubes de etiquetas 3D con soporte de medios enriquecidos, seguridad de tipos de TypeScript e interacción preparada para móviles — todo sin agregar una sola dependencia.


Fin del Artículo — Basado en el análisis del código fuente de @xingwangzhe/tags-cloud v0.9.0

Compartir esta página