import { WordCloud, prepareWordCloudLayout } from "semiotic/wordcloud"
Native text marks arranged with d3-cloud 2.0. A cloud offers an impression of frequent terms; pair it with exact values because word length and shape also affect apparent prominence.
Explore A story takes shape for masks with holes, inside/outside occupancy, linked reading, keyboard inspection and exports.
Prepare once, render the same placements
JSX
import { prepareWordCloudLayout, WordCloud } from "semiotic/wordcloud" const options = { data: [{ text: "care", value: 34 }, { text: "trust", value: 25 }], width: 640, height: 400, fontFamily: "Arial", seed: 42 } // Run in a browser after loading the intended font, or supply a Canvas adapter. const layout = await prepareWordCloudLayout(options) // Keep options and layout together when caching or serializing. <WordCloud {...options} layout={layout} /> // On the server, no Canvas dependency or layout computation is needed: import { renderChartWithEvidence, renderToImage } from "semiotic/server" const { svg, evidence } = renderChartWithEvidence("WordCloud", { ...options, layout }) const png = await renderToImage("WordCloud", { ...options, layout }) console.log(evidence.wordCloud) // placed count, omissions, mask and font identity
Synchronous server/MCP calls reject missing or stale layouts. Changing data, mask, font, rotation, seed or plot dimensions requires preparation again. Color, selection and tooltips reuse geometry. Server PNG exports require the intended font to be available to Sharp’s text renderer (for example through the host font configuration). Saving coordinates does not embed a font in a server SVG.
Preparation yields between small batches so controls and resize events can run. React cancels obsolete work automatically. For manual preparation, pass an AbortSignal as the third argument: prepareWordCloudLayout(options, environment, controller.signal). Aborting stops placement between words and rejects with the signal’s reason.
Silhouettes and omissions
JSX
const mask = { type: "svgPath", path: "M0 0H200V200H0Z M60 60H140V140H60Z", viewBox: [0, 0, 200, 200], fillRule: "evenodd", // preserves the central hole mode: "inside" } <WordCloud data={data} mask={mask} seed={42} onLayout={layout => { console.log(layout.words.length, layout.omitted) }} />
Each input row has exactly one outcome: a placed word or an omission with its source index and reason. Duplicate IDs, missing labels, invalid values, term limits, failed rasterization and lack of space remain distinguishable. The hidden mask obstacle never counts as a mark.
Shared network frame
WordCloud uses StreamNetworkFrame with a custom layout and text render backend. Prepared word bounds supply its hit targets; the frame owns painting, pointer and keyboard interaction, selection, and SVG rendering. No separate word-cloud frame is used.
Fonts, Node and interaction
Browser preparation awaits font loading. Node preparation accepts a second argument with canvas, path and loadImage adapters plus an optional fontIdentity; Semiotic does not install a native Canvas package. Layout JSON records font settings and fingerprints, not font files. Font substitution on another host can change the painted ink.
Tab reaches the network frame; Home selects a term and arrows move spatially. Enter/Space activates the original datum, and Escape dismisses its tooltip. Hit testing uses stored rotated bounds. Shape changes repack discretely; there is no incremental push API or layout animation.
| Prop | Type | Required | Default | Description |
|---|
data | array | Yes | — | Already aggregated terms. The chart does not tokenize text or remove stop words. |
layout | object | — | — | Portable prepareWordCloudLayout result. Optional in React; required for server/MCP rendering. Data and all arrangement options must match. |
textAccessor | string | function | — | "text" | Term label. |
valueAccessor | string | function | — | "value" | Positive finite term weight. |
idAccessor | string | function | — | — | Stable identity, defaulting to term text. First valid duplicate wins; remaining rows are reported as omissions. |
width | number | — | 640 | Outer width. Layout dimensions are the inner rectangle after explicit margin. |
height | number | — | 400 | Outer height. Inner dimensions must be integer pixels from 1 through 2040. |
fontFamily | string | — | "sans-serif" | Font to load before preparation. Use the same font file and raster environment for reproducible placement. |
fontSizeRange | array | — | [12, 64] | Minimum and maximum font sizes; words too large to fit remain in omitted. |
fontSizeScale | string | — | "sqrt" | sqrt, linear or log mapping of weight relative to the largest term. |
rotate | string | array | — | "horizontal" | horizontal, orthogonal, or explicit angles in degrees. |
seed | number | — | 42 | Controls rotations and candidate positions. Equal fonts, dimensions and options are also needed for determinism. |
padding | number | — | 1 | Collision padding around each word in pixels. |
maxWords | number | — | 250 | Highest-weight terms admitted to placement. Others are reported with reason max-words. |
mask | object | — | — | {type:'svgPath', path, viewBox, fillRule?, mode?} or {type:'image', src, mode?}. Inside mode permits the shape; outside mode occupies it as an obstacle. |
maskFit | string | — | "contain" | Centered contain or cover fit; SVG holes respect fillRule. |
maskThreshold | number | — | 128 | Alpha threshold from 1 to 255. Image URLs require same origin or CORS. |
margin | number | object | — | 0 | Explicit outer padding. No axis margins are reserved. |
groupHulls | array | — | — | Rounded enclosures in the network background layer: { id, ids, label?, color?, padding? }. ids are stable term IDs; only placed members contribute. Groups may overlap without repacking words. Available in Canvas, SVG and server output. |
renderAs | string | — | "canvas" | canvas or svg. Both paint the same retained text placements. Forced colors uses SVG. |
colorBy | string | function | — | — | Optional categorical color accessor; colorScheme accepts a named palette, array or mapping. |
title | string | — | — | Accessible title; does not reserve visible title space. |
description | string | — | — | Accessible reading guidance. |
summary | string | — | — | Accessible task summary. |
accessibleTable | boolean | object | — | true | Source values with placement/omission status. Keep enabled unless providing an equivalent reading. |
tooltip | boolean | function | object | — | — | Original source datum; false/null/empty content suppresses the tooltip without disabling linked hover. |
linkedHover | boolean | string | object | — | — | Named linked selection. String accessors supply the default identity field. With callback accessors, provide raw source fields explicitly, e.g. linkedHover={{ fields: ["term"] }}. |
selection | object | — | — | Consume a named selection to dim other terms. |
annotations | array | — | — | {id, label, dx?, dy?} annotations anchored to placed term IDs. |
onLayout | function | — | — | Receives immutable placements, omitted rows and diagnostics after preparation. |
onLayoutError | function | — | — | Receives a typed WordCloudLayoutError, including missing Canvas, invalid mask or stale layout. |
onClick | function | — | — | Original datum and plot point; also invoked by Enter or Space on a focused term. |