d3-cloud

A canvas-based word cloud layout engine for JavaScript, arranging words by size with spiral collision detection and optional rotation.

Library
npm
v1.2.9
3,947stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
47/100Fair
Development Activity8
Maintenance0
Community80
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
62/100Good
Architecture72
Code Quality45
Innovation62
Learning Curve68

d3-cloud is a Wordle-inspired word cloud layout library that computes non-overlapping positions for a set of words, sized and optionally rotated, using an HTML5 canvas for fast pixel-level collision detection. It does not render anything itself; instead it dispatches “word” and “end” events with placement data (x, y, rotation) that consuming code, typically D3.js, uses to draw the final SVG or canvas visualization.

Because the layout algorithm is decoupled from rendering, d3-cloud works equally well in the browser (using the native <canvas> element) or in Node.js (using the canvas npm package as a drop-in replacement), making it a common building block for both client-side dashboards and server-side static image generation of tag clouds.

What You Get

  • A configurable cloud() layout generator with chainable accessors for size, font, fontSize, fontStyle, fontWeight, rotate, padding, spiral, and random number source
  • Two built-in spiral placement strategies (archimedean and rectangular) plus support for supplying a custom spiral generator function
  • An event-driven API (on("word", ...) and on("end", ...)) that streams placement results incrementally as each word is successfully positioned
  • Pluggable canvas support via the canvas() accessor, letting the same layout code run in a browser or in Node.js with the canvas package
  • Per-word customization via accessor functions, so font, size, rotation, and padding can each be derived from the underlying data

Common Use Cases

  • Rendering tag clouds of keyword frequency data with D3.js in analytics dashboards
  • Generating word cloud images server-side in Node.js for reports, social cards, or static exports
  • Building interactive text visualizations where word size encodes a metric like frequency, sentiment, or importance
  • Prototyping custom text-layout visualizations that need spiral or mask-based collision avoidance rather than a rigid grid

Under The Hood

Architecture The entire layout algorithm lives in a single file, index.js (401 lines), exporting a factory function that returns a “cloud” object built from closures over private state (size, words, spiral, canvas) rather than a class. cloud.start() sorts words by size descending, then drives an incremental placement loop via setInterval(step, 0) (throttled by the configurable timeInterval) so it doesn’t block the browser’s event loop; each step calls cloudSprite() to rasterize an upcoming word onto an offscreen canvas and extract a monochrome bitmask, then place() walks the configured spiral function (archimedeanSpiral or rectangularSpiral) testing candidate coordinates against a shared bitpacked board array via cloudCollide(), which performs 32-bit-word bitwise AND checks for fast overlap detection. Successful placements are broadcast through a d3-dispatch event emitter (“word” and “end” events), decoupling layout computation from rendering entirely — the module never touches the DOM beyond acquiring a canvas via the pluggable canvas() accessor.

Tech Stack Written in plain JavaScript with no build-time framework; the only runtime dependency is d3-dispatch (^1.0.3) for its event emitter, and browserify (^17.0.0) is the sole devDependency, used to bundle build/d3.layout.cloud.js as a standalone UMD build via the npm build script defined in package.json. The package ships both a CommonJS entry (index.js, main) and an ESM-friendly entry (module/jsnext:main both pointing at index) for tree-shaking bundlers, and it depends on the HTML5 canvas API — either the browser’s native implementation or the canvas npm package in Node, as shown in examples/node.js.

Code Quality There are no automated tests anywhere in the repository (no test directory or spec files, and no test script in package.json) — correctness relies entirely on manual verification via the demos in examples/browserify.js and examples/node.js. The code favors dense, low-level bit-twiddling (bitwise shifts, packed 32-bit board arrays) with terse variable names (d, sw, lx, sx, msx) and minimal inline comments, trading readability for performance in the hot collision-detection path; there is no TypeScript, no JSDoc type annotations, and error handling is essentially absent, with a ”// TODO reuse arrays?” and ”// Temporary hack” comment in index.js flagging known unaddressed rough edges.

API Design The API follows D3’s getter/setter accessor pattern (size(), font(), rotate(), each doubling as a getter when called with no arguments and a chainable setter when called with one), which gives it a low learning curve for anyone already familiar with D3.js conventions, and the README documents every accessor with its default value inline. Getting started requires only a handful of lines (cloud().size(…).words(…).on(“end”, draw).start()), but because the module deliberately does no rendering, first-time users must write their own draw callback to turn placement data into SVG or canvas output, which adds friction beyond the layout call itself; the lack of TypeScript types also means editors provide no autocomplete for the accessor surface.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search