D3 Word Cloud Layout
d3-cloud is a JavaScript library for generating Wordle-inspired word clouds, leveraging HTML5 canvas and sprite masks for efficient rendering. It provides a programmatic API to configure cloud properties such as size, word list, font face, font style, font weight, and font size accessor functions. The library integrates well within the D3.js ecosystem, although it can be used standalone to generate word layouts. The current stable version is 1.2.9, indicating a mature and stable codebase rather than one undergoing rapid iterative development. Key differentiators include its canvas-based approach for performance and its comprehensive layout algorithm that handles word placement and collision detection, contrasting with purely SVG-based solutions or those requiring manual positioning. Its primary output is an array of word objects with calculated positions, sizes, and rotations, ready for custom rendering.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'cloud')
cause The d3-cloud library was not imported or initialized correctly, or the global 'd3' object (for legacy usage) was not available when d3-cloud was loaded.fixFor modern usage, ensure you are using `import cloud from 'd3-cloud';` and then `cloud()`. For legacy D3 integration, ensure the `d3` library is loaded globally before `d3-cloud`'s script. -
TypeError: layout.start is not a function
cause The `cloud()` function was not invoked to create a layout instance before attempting to call its methods, or the import was incorrect.fixEnsure you create an instance of the layout: `const layout = cloud();` (for modern ESM) or `const layout = d3.layout.cloud();` (for legacy global D3). -
Some words are not appearing in the final word cloud, even if space seems available.
cause The d3-cloud algorithm attempts to place words along a spiral. If a word cannot find an uncollided position within its search, it is discarded.fixIncrease the `size` of the layout, decrease `padding`, adjust the `fontSize` accessor to make words smaller (e.g., `d => Math.sqrt(d.value) * 5` instead of `* 10`), or reduce the total number of words in the input array. Check the output of the 'end' event to identify which words were dropped.
Warnings
- gotcha Words that cannot be placed within the specified layout size (due to collisions or insufficient space) are silently omitted from the final output array. Users expecting all input words to always appear might be surprised.
- breaking d3-cloud was originally designed for older D3 versions (v3-v4) and could extend the global `d3` object (e.g., `d3.layout.cloud()`). Modern D3 (v5+) and module bundlers require importing `d3-cloud` as a standalone module.
- gotcha The library outputs word position data for rendering on an HTML5 Canvas, not directly for SVG. While the data can be adapted for SVG, the intrinsic sprite mask optimization is specific to canvas.
- gotcha For very large word lists or complex layouts, the layout algorithm can be computationally intensive and might block the browser's event loop, leading to UI freezes. The `timeInterval` method can help mitigate this.
Install
-
npm install d3-cloud -
yarn add d3-cloud -
pnpm add d3-cloud
Imports
- cloud
import { cloud } from 'd3-cloud';import cloud from 'd3-cloud';
- cloud
const cloud = require('d3-cloud'); - d3.layout.cloud
import { cloud } from 'd3-cloud';const layout = d3.layout.cloud();
Quickstart
import cloud from 'd3-cloud';
interface Word {
text: string;
value: number;
size?: number;
x?: number;
y?: number;
rotate?: number;
font?: string;
style?: string;
weight?: string;
}
const wordsData: Word[] = [
{ text: "TypeScript", value: 60 },
{ text: "JavaScript", value: 50 },
{ text: "D3", value: 45 },
{ text: "Cloud", value: 40 },
{ text: "Canvas", value: 35 },
{ text: "Layout", value: 30 },
{ text: "Example", value: 25 },
{ text: "Development", value: 20 },
{ text: "Web", value: 15 },
{ text: "Visualization", value: 55 }
];
const width = 960;
const height = 500;
// Create a new cloud layout instance
const layout = cloud<Word>()
.size([width, height])
.words(wordsData)
.padding(5)
.rotate(() => Math.floor(Math.random() * 5) * 30 - 60) // Rotate words by -60, -30, 0, 30, 60 degrees
.font("Impact")
.fontSize(d => Math.sqrt(d.value) * 8) // Scale font size based on word value
.on("end", (words: Word[], bounds: [{ x0: number, y0: number }, { x1: number, y1: number }]) => {
console.log("Word cloud layout generation complete.");
console.log("Successfully placed words:", words.map(w => ({ text: w.text, size: w.size, x: w.x, y: w.y, rotate: w.rotate })));
console.log("Overall cloud bounds:", bounds);
// In a real application, you would typically render these 'words' to an HTML5 Canvas or SVG element.
});
layout.start(); // Start the layout algorithm