WordCloud3D | svelte-wordcloud Skip to content

WordCloud3D

WordCloud3D renders words across multiple depth layers using WebGL (Three.js via Threlte). The viewer can navigate layers with Ctrl + Wheel, pinch gesture, or the built-in depth scrollbar. The scroll range extends slightly past the last layer so small words there can be inspected up close.

Must be a descendant of WordCloud.

The layout algorithm runs once per unique dataset and configuration. Pass useCache to persist the result to localStorage — subsequent page loads render instantly without re-running the algorithm.

PropTypeDefaultDescription
fontUrlstringRequired. URL of the font file (TTF/OTF/WOFF). Must be self-hosted. Place the file in your project’s public/ directory and pass the path (e.g. '/fonts/MyFont.ttf'). Note: WOFF2 is not supported; use TTF, OTF, or WOFF.
wheelScrollSpeednumber1Multiplier for Ctrl + Wheel and pinch depth-scroll speed.
layoutWordCloud3DLayout{}Layout and sizing options (see below).
a11yWordCloud3DA11y{}Accessibility labels and ARIA text (see below).
onWordClick(word: WordItem) => voidCalled when a word is clicked.
useCachestring | symbol | truePersist the computed layout to localStorage. true derives a key from a hash of the data and layout params. Pass a string or symbol for an explicit key (useful when multiple clouds share a page). Automatically invalidated when data or layout params change. Call clearCache() on the instance to clear manually.
KeyTypeDefaultDescription
layerSpacingnumber12Z-distance between adjacent layers (Three.js world units).
fontSizeContrastnumber2.0Power-curve exponent. Higher = top words dominate more; lower = more uniform sizes.
topWordAreanumber0.22Fraction of viewport area targeted by the largest word.
randomnessnumber0.32Randomness applied to word placement. 0 = grid-like, 1 = maximum scatter.
KeyTypeDefaultDescription
depthValueText(current: number, total: number) => string(c, t) => `Layer ${c} / ${t}`aria-valuetext for the built-in depth slider. Use for localisation.
depthLabelstring'Depth'Accessible label text for the depth slider.
panHintstring'Arrow keys to pan'Short visible hint shown inside the keyboard pan control when focused.
panLabelstring'Pan camera. Use arrow keys to move the view.'Screen-reader description for the keyboard pan control button.
resetPanLabelstring'Reset pan (double-click)'Screen-reader label for the reset pan button.
fullscreenLabelstring'Enter fullscreen'Screen-reader label for the enter-fullscreen button.
exitFullscreenLabelstring'Exit fullscreen'Screen-reader label for the exit-fullscreen button.
<script lang="ts">
import { WordCloud, WordCloud3D, WordCloudLabel } from '@shamokit/svelte-wordcloud';
import type { WordItem } from '@shamokit/svelte-wordcloud';
// Place your font file in public/fonts/ and reference it by path.
// External CDN URLs are blocked in production; self-hosting is required.
const FONT_URL = '/fonts/NotoSansJP.ttf';
const words: WordItem<{ link?: string }>[] = [
{ word: 'Svelte', counts: 120, link: 'https://svelte.dev' },
{ word: 'TypeScript', counts: 95, link: 'https://www.typescriptlang.org' },
{ word: 'Vite', counts: 80, link: 'https://vitejs.dev' },
{ word: 'Three.js', counts: 70, link: 'https://threejs.org' },
{ word: 'WebGL', counts: 60 },
{ word: 'Threlte', counts: 55, link: 'https://threlte.xyz' },
// add more words...
];
function handleWordClick(word: WordItem<{ link?: string }>) {
if (word.link) window.open(word.link, '_blank');
}
</script>
<WordCloud data={words} --wc-background="#0d0d1a" --wc-color="#7ec8e3">
<WordCloudLabel>
{#snippet label({ props })}
<span {...props} style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)">
Technology word cloud
</span>
{/snippet}
</WordCloudLabel>
<WordCloud3D fontUrl={FONT_URL} onWordClick={handleWordClick} useCache={true} />
</WordCloud>
<script lang="ts">
import { WordCloud, WordCloud3D } from '@shamokit/svelte-wordcloud';
let cloudRef = $state<{ clearCache(): void } | null>(null);
</script>
<WordCloud data={words}>
<WordCloud3D fontUrl={FONT_URL} useCache="my-3d-cloud" bind:this={cloudRef} />
</WordCloud>
<button onclick={() => cloudRef?.clearCache()}>Clear cache</button>