@xingwangzhe/tags-cloud: Der Multi-Modale 3D-Tag-Cloud-Engine, Gebaut auf Reiner Mathematik
@xingwangzhe/tags-cloud: Der Multi-Modale 3D-Tag-Cloud-Engine, Gebaut auf Reiner Mathematik
GitHub: xingwangzhe/tags-cloud · Demo: tagscloud.needhelp.icu · npm: @xingwangzhe/tags-cloud · Lizenz: MIT · Version: v0.9.0
1. Einleitung: Die 3D-Tag-Cloud für das Moderne Web Neudenken
Die Tag-Cloud ist seit über zwei Jahrzehnten ein fester Bestandteil der Web-Visualisierung — sie hat sich von einfachen gewichteten Wortlisten zu immersiven dreidimensionalen Erlebnissen entwickelt, die Nutzer fesseln und alltägliche Textsammlungen in interaktive räumliche Skulpturen verwandeln. Einer der einflussreichsten Beiträge zu dieser Entwicklung ist cong-min/TagCloud, eine schlanke JavaScript-Bibliothek, die zeigte, wie eine Sphäre rotierender Textlabels mit minimalem Aufwand und null externen Abhängigkeiten realisiert werden kann. Mit 390 Sternen und 93 Forks auf GitHub etablierte die originale TagCloud ein Entwurfsmuster, das unzählige Entwickler für Portfolio-Seiten, Skill-Showcases und Datenvisualisierungs-Dashboards übernommen haben. Ihre Kerninnovation bestand darin, zu beweisen, dass 3D-Tag-Clouds nicht auf schwere WebGL-Frameworks oder externe Rendering-Engines angewiesen sind; stattdessen können einfache trigonometrische Berechnungen in Kombination mit sorgfältiger DOM-Positionierung überraschend überzeugende visuelle Ergebnisse liefern.
Dann kommt @xingwangzhe/tags-cloud — eine komplette Neuerfindung des 3D-Tag-Cloud-Konzepts, die die mathematische Eleganz ihres Vorgängers bewahrt und gleichzeitig die Fähigkeiten dramatisch erweitert, die Architektur modernisiert und die Grenzen dessen verschiebt, was eine Tag-Cloud rendern kann. Dies ist nicht bloß ein Fork oder eine Feature-Erweiterung; es stellt einen fundamentalen architektonischen Wandel dar — von einem reinen Text-, DOM-lastigen Renderer zu einem multi-modalen Engine, der Text, Bilder, SVG-Grafiken, beliebiges HTML, Video-Elemente und sogar vollständige Web Components anzeigen kann — alles rotiert gemeinsam in einem mathematisch präzisen dreidimensionalen Raum. Die Bibliothek erreicht diese Vielseitigkeit bei einem außergewöhnlich kompakten Footprint von etwa 3KB gzipped, hat null Runtime-Abhängigkeiten und wurde mit einer durch und durch modernen Toolchain aus Bun als JavaScript-Runtime, Vite als Bundler und TypeScript für vollständige Typsicherheit entwickelt.
Der Slogan des Projekts — “multi-modal 3D tag cloud · pure math engine” — fasst seine doppelte Identität zusammen. Einerseits ist es eine praktische UI-Komponentenbibliothek, die Entwickler in jedes Webprojekt einbauen können, um visuell beeindruckende Tag-Sphären zu erstellen. Andererseits ist es eine mathematische Engine, die das komplexe Problem des 3D-Tag-Cloud-Renderings in drei reine, deterministische und wunderschön trennbare geometrische Operationen zerlegt: Fibonacci-Sphärenverteilung für die Anfangspositionierung, Rotationsmatrix-Multiplikation für die räumliche Transformation und perspektivische Projektion für tiefenbewusstes 2D-Rendering. Jede dieser Operationen ist in einem eigenen dedizierten Modul innerhalb des Verzeichnisses src/core/ implementiert, was die Codebasis nicht nur hochgradig wartbar macht, sondern auch eine hervorragende Lernressource für alle darstellt, die die Mathematik hinter der 3D-Computergrafik verstehen wollen — ohne die verschleiernde Komplexität einer vollständigen Rendering-Pipeline.
Die folgenden Abschnitte bieten einen umfassenden technischen Deep-Dive in jeden Aspekt von @xingwangzhe/tags-cloud — vom auf dem Goldenen Schnitt basierenden Sphärenverteilungsalgorithmus bis zum quaternioneninspirierten Arcball-Interaktionsmodell, von der dualen Canvas/DOM-Rendering-Architektur bis zu den Responsive-Design-Überlegungen, die es auf Desktop und Mobilgeräten nahtlos funktionieren lassen. Ob Sie ein Entwickler sind, der diese Bibliothek für Ihr nächstes Projekt evaluiert, ein Grafikprogrammierer, der sich für leichte 3D-Techniken interessiert, oder ein Mathematiker, der neugierig auf die realen Anwendungen des Fibonacci-Gitters ist — dieser Artikel bietet detaillierte Erklärungen, mathematische Herleitungen, Architekturdiagramme und kommentierte Codebeispiele, um jede Facette dieses bemerkenswerten Software-Stücks zu beleuchten.
2. Die Mathematische Grundlage: Drei Säulen des 3D-Renderings
Im Kern von @xingwangzhe/tags-cloud liegt ein Trio mathematischer Operationen, die zusammengenommen eine abstrakte Liste von Inhaltselementen in eine visuell kohärente rotierende Sphäre verwandeln. Diese Operationen — Verteilung, Rotation und Projektion — sind in drei dedizierten Modulen unter src/core/ implementiert, jedes verantwortlich für eine einzige geometrische Transformation. Diese Trennung der Belange ist nicht bloß eine architektonische Präferenz; sie spiegelt die grundlegende Struktur von 3D-Computergrafik-Pipelines wider, in denen Vertex-Generierung, Modell-Transformation und Kamera-Projektion eigenständige Stufen sind, die unabhängig optimiert, getestet und verstanden werden können.
flowchart LR
subgraph Input["📥 Eingabeschicht"]
TAGS["TagItem[]
(text | image | SVG | HTML | video | element)"]
OPTS["TagCloudOptions
(radius, spin, colors, callbacks)"]
end
subgraph CoreEngine["⚙️ Pure Math Engine (src/core/)"]
direction TB
DIST["🔵 distribution.ts
Fibonacci-Sphäre
N Punkte → 3D-Koordinaten"]
ROT["🟢 rotation.ts
Rotationsmatrizen
3D Punkte → rotierte 3D Punkte"]
PROJ["🔴 projection.ts
Perspektivische Projektion
rotierte 3D → 2D + Tiefe"]
end
subgraph RenderLayer["🎨 Render-Schicht"]
direction TB
CANVAS["Canvas 2D API
(Text + Bilder)"]
DOM["DOM Overlay
(SVG + HTML + Video + Elemente)"]
end
subgraph Interaction["👤 Interaktionsschicht"]
MOUSE["Maus / Touch Drag"]
INERTIA["Trägheitsabklingen
(0.96/Frame)"]
end
TAGS --> DIST
OPTS --> DIST
DIST -->|"Vec3[]"| ROT
ROT -->|"Rotierte Vec3[]"| PROJ
PROJ -->|"ProjectedTag[]
(x, y, z, scale, alpha)"| CANVAS
PROJ --> DOM
MOUSE --> INERTIA
INERTIA -->|"Rotationswinkel"| 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 Fibonacci-Sphärenverteilung: Die Goldene Geometrie der Punktplatzierung
Der erste und wohl ästhetisch kritischste Schritt bei der Erstellung einer 3D-Tag-Cloud ist die Bestimmung, wo jeder Tag auf der Sphäre positioniert werden soll. Ein naiver Ansatz könnte Tags in regelmäßigen Breiten- und Längengrad-Abständen platzieren, aber dies führt unweigerlich zu einer Häufung an den Polen, wo die Meridiane zusammenlaufen, und zu dünn besiedelten Regionen am Äquator. Der Fibonacci-Sphären-Algorithmus löst dieses Problem elegant, indem er eine Verteilung von Punkten erzeugt, die über die gesamte Sphärenoberfläche bemerkenswert gleichmäßig ist — ohne sichtbare Häufungen oder Lücken, unabhängig von der Anzahl der Punkte.
Dieser Algorithmus verdankt seinen Namen dem Goldenen Schnitt (\varphi = \frac{1 + \sqrt{5}}{2} \approx 1.6180339887), einer mathematischen Konstante, die in der Natur in Strukturen von Sonnenblumenkern-Anordnungen bis zu Nautilus-Schneckenhaus-Spiralen vorkommt. Die Verbindung zu den Fibonacci-Zahlen — der Folge, in der jeder Term die Summe der beiden vorhergehenden ist — besteht darin, dass das Verhältnis aufeinanderfolgender Fibonacci-Zahlen mit fortschreitender Folge gegen den Goldenen Schnitt konvergiert. Im Kontext der Sphärenverteilung sorgt die Irrationalität des Goldenen Schnitts dafür, dass aufeinanderfolgende Punkte immer in Winkeln platziert werden, die sich niemals wiederholen, wodurch ein aperiodisches Spiralenmuster entsteht, das die Sphärenoberfläche gleichmäßig ausfüllt.
Die spezifische Implementierung in src/core/distribution.ts verwendet eine Variante des Fibonacci-Gitters, die für die sphärische Abbildung optimiert wurde. Für eine Sphäre mit Radius (R) und (N) zu verteilenden Punkten berechnet der Algorithmus die sphärischen Koordinaten und wandelt sie dann für jeden Punkt (i \in {0, 1, 2, \ldots, N-1}) in kartesische Koordinaten ((x, y, z)) um. Der Breitengrad-Winkel (\phi) (gemessen von der positiven z-Achse, d.h. vom Nordpol) wird mit der inversen Kosinusfunktion berechnet, um eine gleichmäßige Verteilung entlang der z-Achse zu gewährleisten:
Diese Formel platziert den ersten Punkt knapp unterhalb des Nordpols und den letzten Punkt knapp oberhalb des Südpols, wobei der (+0.5)-Offset (eingebettet in den Zähler (2i + 1)) sicherstellt, dass kein Punkt jemals genau auf einem Pol landet. Diese subtile Anpassung ist entscheidend, da sie den visuellen Artefakt eines Tags verhindert, der direkt oben oder unten auf der Sphäre sitzt, wo die Rotation kaum wahrnehmbar wäre. Die (\arccos)-Funktion wandelt einen gleichmäßig verteilten linearen Parameter in eine kosinusgewichtete Winkelverteilung um, die kompensiert, dass Sphären in Polnähe weniger und in Äquatornähe mehr Oberfläche haben.
Der Längengrad-Winkel (\theta) (gemessen in der xy-Ebene von der positiven x-Achse) wird durch eine Skalierung von (\phi) mit (\sqrt{N\pi}) berechnet, was das charakteristische Spiralenmuster erzeugt:
Der Faktor (\sqrt{N\pi}) leitet sich aus der Beziehung zwischen dem Goldenen Winkel und der Gesamtoberfläche der Sphäre ab. Mit zunehmendem (N) stellt diese Skalierung sicher, dass die Spirale sich die angemessene Anzahl von Malen um die Sphäre windet, um gleichmäßige Abstände zwischen benachbarten Punkten zu erhalten. Das Ergebnis ist ein Muster, bei dem jeder aufeinanderfolgende Punkt um etwa den Goldenen Winkel (\approx 137.5°) relativ zu seinem Vorgänger gedreht ist — betrachtet entlang der z-Achse — und damit die in der Natur vorkommenden phyllotaktischen Spiralen widerspiegelt.
Schließlich werden diese sphärischen Koordinaten mit der Standardtransformation in kartesische Koordinaten umgewandelt:
Die resultierenden Punkte erfüllen die Sphärengleichung (x_i^2 + y_i^2 + z_i^2 = R^2) und sind mit einer Gleichmäßigkeit verteilt, die viel rechenintensiveren optimierungsbasierten Methoden Konkurrenz macht. Die folgende Darstellung fasst den vollständigen Fibonacci-Sphären-Algorithmus zusammen:
Die TypeScript-Implementierung in src/core/distribution.ts ist bemerkenswert prägnant und spiegelt die elegante Einfachheit des Algorithmus wider:
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;}Diese Funktion gibt ein Array von Vec3-Objekten zurück, die als Anfangspositionen für alle Tags in der Cloud dienen. Der Algorithmus läuft in (\mathcal{O}(N))-Zeit, was ihn für Tag-Clouds mit Hunderten von Elementen geeignet macht. In der Praxis enthalten die meisten Tag-Clouds zwischen 20 und 100 Tags, wofür diese Berechnung praktisch augenblicklich erfolgt.
2.2 3D-Rotation: Matrixmultiplikation im Räumlichen Bereich
Sobald die Tags auf der Sphärenoberfläche positioniert sind, besteht der nächste Schritt darin, die Rotation zu ermöglichen — sowohl die kontinuierliche automatische Drehung als auch die benutzergesteuerte Zieh-Interaktion. Die Bibliothek implementiert die Rotation mit zusammengesetzten achsenausgerichteten Rotationsmatrizen, speziell aufeinanderfolgenden Rotationen um die Y-Achse gefolgt von der X-Achse. Dieser Ansatz ist recheneffizient, leicht verständlich und für den Tag-Cloud-Anwendungsfall, bei dem Rotationen immer relativ zu einer im Ursprung zentrierten Sphäre sind, völlig ausreichend.
Die mathematische Grundlage für diese Rotationen stammt aus der linearen Algebra. Eine 3D-Rotationsmatrix ist eine (3 \times 3) orthogonale Matrix mit Determinante 1, die die Koordinaten eines Punktes transformiert, während sie seinen Abstand zum Ursprung beibehält. Für die Rotation um einen Winkel (\alpha) um die Y-Achse lautet die Rotationsmatrix (R_y(\alpha)):
Für die Rotation um einen Winkel (\beta) um die X-Achse lautet die Rotationsmatrix (R_x(\beta)):
Die Bibliothek wendet diese Rotationen nacheinander an: zuerst die Y-Achsen-Rotation, dann die X-Achsen-Rotation. Für einen Punkt (P = (x, y, z)) erzeugt die Y-Achsen-Rotation einen Zwischenpunkt (P’):
Die X-Achsen-Rotation wird dann auf (P’) angewendet, um den endgültig rotierten Punkt (P’’) zu erzeugen:
Die Implementierung in src/core/rotation.ts expandiert diese Matrixmultiplikationen zu direkten arithmetischen Operationen und vermeidet so den Overhead der Matrixobjekt-Allokation und -Multiplikation. Für einen einzelnen Punkt berechnet die Rotationsfunktion:
Die rotatePoints-Funktion führt diese Transformation batchweise für alle Tags durch:
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 Perspektivische Projektion: Vom 3D-Raum auf den 2D-Bildschirm
Die letzte mathematische Operation wandelt die rotierten 3D-Koordinaten in 2D-Bildschirmpositionen um. Die Bibliothek verwendet ein vereinfachtes, aber äußerst effektives Projektionsmodell, das einen Skalierungsfaktor und einen Deckkraftfaktor basierend auf der Tiefe berechnet, mit einem Perspektiv-Tiefenparameter, der dem doppelten Sphärenradius entspricht:
Der Deckkraftfaktor (Alpha) verwendet eine quadratische Beziehung mit einer Bias-Anpassung:
Die vollständige Projektions-Pipeline wird wie folgt zusammengefasst:
Die TypeScript-Implementierung spiegelt diese Mathematik präzise wider:
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. Architektur und Moduldesign
Die Codebasis zeichnet sich durch saubere Softwarearchitektur aus, die durch bewusste Trennung von mathematischer Berechnung, Rendering-Orchestrierung und Benutzerinteraktionsbehandlung erreicht wird.
3.1 Die Pure Math Engine: src/core/
| Modul | Funktion | Eingabe | Ausgabe | Kernformel |
|---|---|---|---|---|
| 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 Das Duale Rendering-System: Canvas + DOM
Eine der bedeutendsten Innovationen ist das duale Rendering-System, das die Canvas 2D API für Text und Bilder und das DOM-Overlay für SVG, HTML, Video und Web Components verwendet.
flowchart TB
subgraph "Tag-Typen & Renderer"
direction LR
TEXT["📄 Text-Tag"]
IMG["🖼️ Bild-Tag"]
SVG_TAG["🎨 SVG-Tag"]
HTML_TAG["🌐 HTML-Tag"]
VIDEO["🎬 Video-Tag"]
ELEMENT["🔧 Element-Tag"]
end
subgraph "Renderer-Auswahl"
CANVAS["Canvas 2D API
✅ Text
✅ Bilder"]
DOM["DOM Overlay
✅ 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. Leistungsmerkmale
4.1 Rechenkomplexität
| Stufe | Komplexität | Dominante Operationen |
|---|---|---|
| Rotation | O(N) | 8 Mul + 4 Add pro Punkt |
| Projektion | O(N) | 1 Div + 2 Mul + 1 Add pro Punkt |
| Z-Sortierung | O(N log N) | Vergleichsbasierte Sortierung |
| Canvas-Rendering | O(N) | fillText / drawImage-Aufrufe |
| DOM-Update | O(N) | transform + opacity setzen |
4.2 Speichereffizienz
Für (N = 100) Tags beträgt der gesamte numerische Zustand etwa (100 \times (3 + 5) \times 8 = 6.400) Bytes — weniger als 7KB Gleitkommazahlen.
4.3 Bundle-Größe
| Format | Größe |
|---|---|
| ESM (dist/index.js) | ~12 KB |
| Gzip | ~3 KB |
| Brotli | ~2,5 KB |
5. Multi-Modale Inhalte: Sechs Tag-Typen
| Tag-Typ | Eingabeformat | Renderer | Interaktivität | Anwendungsfall |
|---|---|---|---|---|
| Text | string | Canvas 2D | onTagClick-Callback | Fähigkeiten, Schlüsselwörter |
| Bild | { type:“image”, src, w, h } | Canvas 2D | onClick pro Tag | Logos, Avatare |
| SVG | { type:“svg”, content, w, h } | DOM | onClick pro Tag | Vektor-Icons |
| HTML | { type:“html”, html } | DOM | onClick pro Tag | Formatierter Rich-Text |
| Video | { type:“video”, src, w, h } | DOM | Vollbild bei Klick | Demo-Clips |
| Element | { type:“element”, element } | DOM | Native DOM-Events | Web Components |
6. Vergleich mit cong-min/TagCloud
| Aspekt | cong-min/TagCloud | @xingwangzhe/tags-cloud | Verbesserung |
|---|---|---|---|
| Sprache | JavaScript (ES5) | TypeScript | Vollständige Typsicherheit |
| Bundle-Größe | ~6KB minified | ~3KB gzipped | ~50% kleiner |
| Abhängigkeiten | 0 | 0 | Beide ohne Abhängigkeiten |
| Tag-Typen | Nur Text | Text, Bild, SVG, HTML, Video, Element | 6x Inhaltsmodalitäten |
| Renderer | Nur DOM | Canvas 2D + DOM hybrid | Bessere Leistung |
| Build-Tool | Rollup + Babel | Vite + Bun + Oxlint | Moderne Toolchain |
| Zieh-Interaktion | Basis-Maus-Drag | Arcball-Stil + Trägheit | Natürlicheres Gefühl |
| Touch-Support | Nicht explizit | Vollständiger Touch + mobile CSS | Mobil bereit |
7. Praktische Anwendungsanleitung
7.1 Basis-Text-Cloud
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 Multi-Modale Cloud
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 Lebenszyklus-Management
const cloud = new TagCloud(container, { tags, spinY: 0.2 });cloud.setTags(["New", "Set", "Of", "Tags"]);cloud.pause();cloud.resume();cloud.destroy();8. Fazit: Mathematik als Rendering-Engine
@xingwangzhe/tags-cloud ist eine überzeugende Demonstration dafür, dass die leistungsfähigste Rendering-Engine in der Software keine GPU, kein Shader-Compiler und kein Framework ist — es ist die Mathematik. Indem das Problem der 3D-Tag-Cloud-Visualisierung in drei reine mathematische Operationen zerlegt wird — Fibonacci-Sphärenverteilung, Rotationsmatrix-Multiplikation und perspektivische Projektion — erzielt die Bibliothek Ergebnisse, die von WebGL-basierten Alternativen visuell nicht zu unterscheiden sind, ohne deren Komplexität, Hardware-Abhängigkeiten oder Bundle-Gewicht zu benötigen.
Die Beiträge des Projekts zum Open-Source-Ökosystem sind dreifach. Architektonisch beweist es, dass ein hybrider Canvas/DOM-Renderer sowohl Leistung als auch Vielseitigkeit in einem 3KB-Paket liefern kann. Mathematisch bietet es saubere, gut dokumentierte Implementierungen fundamentaler 3D-Grafikalgorithmen. Praktisch gibt es Entwicklern eine einsatzbereite Komponente zur Erstellung von 3D-Tag-Clouds mit Rich-Media-Unterstützung, TypeScript-Sicherheit und mobiler Interaktion — ganz ohne eine einzige zusätzliche Abhängigkeit.
Ende des Artikels — Basierend auf der Quellcode-Analyse von @xingwangzhe/tags-cloud v0.9.0