Skip to main content
Version: Next 🚧

Word clouds

WordCloud lays out weighted labels without overlaps. Placement, color selection, and automatic orientation are deterministic for a given seed, so previews and exported frames produce the same composition.

import { Timeline } from "veena/core";
import { WordCloud } from "veena/maths";

const cloud = this.add(WordCloud([
{ text: "AI", weight: 100, featured: true, orientation: "horizontal" },
{ text: "Machine Learning", weight: 94, featured: true, orientation: "horizontal" },
{ text: "Deep Learning", weight: 90, featured: true, orientation: "horizontal" },
{ text: "Neural Network", weight: 86, featured: true, orientation: "horizontal" },
{ text: "Foundation Model", weight: 82, featured: true, orientation: "horizontal" },
{ text: "LLM", weight: 78, featured: true, orientation: "horizontal" },
{ text: "Generative AI", weight: 96, featured: true, orientation: "horizontal" },
{ text: "chatbots", weight: 52 },
{ text: "automation", weight: 46, orientation: "vertical" },
{ text: "deepfakes", weight: 44 },
{ text: "multimodal", weight: 32 },
], {
minimumWordSize: 0.3,
maximumWordSize: 1,
colors: ["#dce2ea", "#aab4c3", "#78a9a2", "#7f94b2", "#9d8fa8"],
})
.size([13.5, 6.3])
.shape("ellipse")
.padding(0.07)
.seed(2026));

Larger weights produce larger words. minimumWordSize is a hard readability floor, while maximumWordSize controls the upper end of the hierarchy. When space is tight, Veena compresses larger words toward the minimum without crossing it. If the words still cannot fit, layout fails with a clear error instead of silently producing illegible text.

The colors array defines the word-color pool. Featured words consistently use its first color; filler words are assigned deterministic colors from the complete set. A word's own color still takes precedence.

Word options​

OptionMeaning
textDisplayed word or phrase. It must not be empty.
weightPositive relative size.
colorOptional per-word color overriding the cloud palette.
featuredPlaces the word in the first, spelled-out reveal group.
orientationOptional "horizontal" or "vertical" preference.

Orientation is semantic rather than degree-based. A horizontal word stays at zero rotation. For a vertical word, Veena deterministically chooses one of the two vertical reading directions. When orientation is omitted, Veena chooses from its default orientation mix.

Paced reveal​

The cloud can author its complete sequence onto an ordinary timeline:

const timeline = new Timeline();

cloud.animate(timeline, {
at: 0.45,
featuredStagger: 0.22,
featuredDuration: 0.55,
pause: 1.25,
fillerStagger: 0.045,
fillerDuration: 0.4,
hold: 1.4,
exitStagger: 0.018,
exitDuration: 0.45,
});

this.play(timeline);

The sequence runs in four phases:

  1. Featured words are spelled out in input order.
  2. The animation waits for pause seconds after the final featured word finishes.
  3. Remaining filler words appear with their own stagger, then the complete cloud remains for hold seconds.
  4. Every word is erased with the configured exit timing.

If no entries are marked featured, all words belong to the opening group and the filler phase is empty.

Timing defaults​

OptionDefaultPurpose
at0Absolute timeline start in seconds.
featuredStagger0.16Delay between featured-word starts.
featuredDuration0.48Spell-out time for each featured word.
pause0.8Gap between featured and filler phases.
fillerStagger0.035Delay between filler-word starts.
fillerDuration0.36Appearance time for each filler word.
hold1Time the complete cloud stays visible.
exitStagger0.012Delay between word-removal starts.
exitDuration0.4Erase time for each word.

Layout and styling​

BuilderPurpose
.size([width, height])Set the cloud's world-space bounds.
.fontRange([minimum, maximum])Map word weights to label heights.
.palette(colors)Set the deterministic automatic color pool.
.shape("ellipse" | "rectangle")Choose the placement boundary.
.padding(value)Set clearance around each word.
.fontFamily(value)Set the label font family.
.fontWeight(value)Set the label font weight.
.seed(value)Reproduce a particular layout.

Each word remains an ordinary label. Use cloud.words for every label, or cloud.featuredWords and cloud.fillerWords when a custom timeline needs direct control instead of cloud.animate(...).

The constructor options and the .fontRange(...)/.palette(...) builders configure the same values. Constructor options are convenient when the cloud's content and visual policy should be declared together; builders remain available for fluent composition.

Run the complete example with:

npm run example -- word-cloud --preview

Source: examples/word-cloud.ts.