Create word clouds in JavaScript.

Overview

Word Cloud Layout

This is a Wordle-inspired word cloud layout written in JavaScript. It uses HTML5 canvas and sprite masks to achieve near-interactive speeds.

See here for an interactive demonstration along with implementation details.

Example cloud of Twitter search results for “amazing”

Usage

See the samples in examples/.

API Reference

# d3.layout.cloud()

Constructs a new cloud layout instance.

# on(type, listener)

Registers the specified listener to receive events of the specified type from the layout. Currently, only "word" and "end" events are supported.

A "word" event is dispatched every time a word is successfully placed. Registered listeners are called with a single argument: the word object that has been placed.

An "end" event is dispatched when the layout has finished attempting to place all words. Registered listeners are called with two arguments: an array of the word objects that were successfully placed, and a bounds object of the form [{x0, y0}, {x1, y1}] representing the extent of the placed objects.

# start()

Starts the layout algorithm. This initialises various attributes on the word objects, and attempts to place each word, starting with the largest word. Starting with the centre of the rectangular area, each word is tested for collisions with all previously-placed words. If a collision is found, it tries to place the word in a new position along the spiral.

Note: if a word cannot be placed in any of the positions attempted along the spiral, it is not included in the final word layout. This may be addressed in a future release.

# stop()

Stops the layout algorithm.

# timeInterval([time])

Internally, the layout uses setInterval to avoid locking up the browser’s event loop. If specified, time is the maximum amount of time that can be spent during the current timestep. If not specified, returns the current maximum time interval, which defaults to Infinity.

# words([words])

If specified, sets the words array. If not specified, returns the current words array, which defaults to [].

# size([size])

If specified, sets the rectangular [width, height] of the layout. If not specified, returns the current size, which defaults to [1, 1].

# font([font])

If specified, sets the font accessor function, which indicates the font face for each word. If not specified, returns the current font accessor function, which defaults to "serif". A constant may be specified instead of a function.

# fontStyle([fontStyle])

If specified, sets the fontStyle accessor function, which indicates the font style for each word. If not specified, returns the current fontStyle accessor function, which defaults to "normal". A constant may be specified instead of a function.

# fontWeight([fontWeight])

If specified, sets the fontWeight accessor function, which indicates the font weight for each word. If not specified, returns the current fontWeight accessor function, which defaults to "normal". A constant may be specified instead of a function.

# fontSize([fontSize])

If specified, sets the fontSize accessor function, which indicates the numerical font size for each word. If not specified, returns the current fontSize accessor function, which defaults to:

function(d) { return Math.sqrt(d.value); }

A constant may be specified instead of a function.

# rotate([rotate])

If specified, sets the rotate accessor function, which indicates the rotation angle (in degrees) for each word. If not specified, returns the current rotate accessor function, which defaults to:

function() { return (~~(Math.random() * 6) - 3) * 30; }

A constant may be specified instead of a function.

# text([text])

If specified, sets the text accessor function, which indicates the text for each word. If not specified, returns the current text accessor function, which defaults to:

function(d) { return d.text; }

A constant may be specified instead of a function.

# spiral([spiral])

If specified, sets the current type of spiral used for positioning words. This can either be one of the two built-in spirals, "archimedean" and "rectangular", or an arbitrary spiral generator can be used, of the following form:

// size is the [width, height] array specified in cloud.size
function(size) {
  // t indicates the current step along the spiral; it may monotonically
  // increase or decrease indicating clockwise or counterclockwise motion.
  return function(t) { return [x, y]; };
}

If not specified, returns the current spiral generator, which defaults to the built-in "archimedean" spiral.

# padding([padding])

If specified, sets the padding accessor function, which indicates the numerical padding for each word. If not specified, returns the current padding, which defaults to 1.

# random([random])

If specified, sets the internal random number generator, used for selecting the initial position of each word, and the clockwise/counterclockwise direction of the spiral for each word. This should return a number in the range [0, 1).

If not specified, returns the current random number generator, which defaults to Math.random.

# canvas([canvas])

If specified, sets the canvas generator function, which is used internally to draw text. If not specified, returns the current generator function, which defaults to:

function() { return document.createElement("canvas"); }

When using Node.js, you will almost definitely override this default, e.g. using the canvas module.

Comments
  • words doesn't show up, goes into infinite loop when integrated in an iPhone app and tested on ipod touch.

    words doesn't show up, goes into infinite loop when integrated in an iPhone app and tested on ipod touch.

    It does show up without an order (words overlapped totally- unreadable) only when the following function is commented out:

    function place(board, tag, bounds) { var perimeter = [{x: 0, y: 0}, {x: size[0], y: size[1]}], startX = tag.x, startY = tag.y, maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), s = spiral(size), dt = Math.random() < .5 ? 1 : -1, t = -dt, dxdy, dx, dy;

     while (dxdy = s(t += dt)) {
       dx = ~~dxdy[0];
       dy = ~~dxdy[1];
    
       if (Math.min(dx, dy) > maxDelta) break;
    
       tag.x = startX + dx;
       tag.y = startY + dy;
    
       if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 ||
           tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
       // TODO only check for collisions within current bounds.
       if (!bounds || !cloudCollide(tag, board, size[0])) {
         if (!bounds || collideRects(tag, bounds)) {
          var sprite = tag.sprite,
               w = tag.width >> 5,
               sw = size[0] >> 5,
               lx = tag.x - (w << 4),
               sx = lx & 0x7f,
               msx = 32 - sx,
               h = tag.y1 - tag.y0,
               x = (tag.y + tag.y0) * sw + (lx >> 5),
               last;
           for (var j = 0; j < h; j++) {
             last = 0;
             for (var i = 0; i <= w; i++) {
               board[x + i] |= (last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0);
             }
             x += sw;
           }
           delete tag.sprite;
           return true;
         }
       }
     }
     return false;
    

    }

    opened by mafazr 14
  • What version of d3 is the http://www.jasondavies.com/wordcloud running on?

    What version of d3 is the http://www.jasondavies.com/wordcloud running on?

    I currently have 3.4.3 of d3 and our word cloud has stopped working from upgrading from d3.v2.js . I wonder if d3-cloud is supported for the latest of d3 right now.

    opened by nmccready 9
  • Ability to provide words + frequency of each word instead of just words

    Ability to provide words + frequency of each word instead of just words

    What do you think about the option to provide a list of word objects that would include the word and the frequency of that word? Might be handy for people who already have the counts calculated for each word to save passing a lot of repeat words.

    opened by babsonmatt 9
  • Padding size has no effect

    Padding size has no effect

    Regardless of what .padding is set to, the Words are always relatively tightly packed.

    I expected more whitespace when I called .padding(10). Is the padding a true/false setting or is there something missing. I don't see the padding value added anywhere in the code, just a check if it is set. If this is intentional, please clarify in the documentation/example.

    opened by gbirke 9
  • Will this be updated for v4?

    Will this be updated for v4?

    I describe this layout in one of the chapters of my book and I'm updating that to the 2nd edition for d3v4 and I was wondering if there will be a v4 version of this chart forthcoming. If not, no worries, I can replace the word cloud section with something else.

    opened by emeeks 8
  • Overlap in wordcloud

    Overlap in wordcloud

    Hello!

    I am aware that there is already a solved post on a very similar issue, but the solution described there does not apply in my case.

    When I try to use the wordcloud layout, I get frequent overlaps.

    For a test case I used the example code from this page with some slight changes and a file with some test words. I uploaded the files on Plunker: http://plnkr.co/edit/MfBFgG4dKCyW2gaNBkhf?p=preview

    The overlaps do not happen every time, but fairly frequently when you do some reloads. I would really like to prevent that.

    Other people reported the same issue and found that it was related to using web fonts or skipping the rotate parameter. This does not apply in my example.

    I suspect that it might be related to the fact that there are to many words for the canvas size, however, I also did tests where I signficantly increased the canvas size and it still happened (though less frequently, as the random placement of the words made it less likely). In addition to that, you can see that several words are not shown at all due to the small canvas size. Why leave some out and create overlap for others? I'm pretty confused by this issue. Is there any mistake on my part?

    opened by anbrun 6
  • Amd

    Amd

    Added bower support, and support for loading as an AMD module

    1. Added bower configuration
    2. Moved source to src/ directory
    3. Wireup so that when used as an AMD module, d3.layout.cloud mixes in with d3
    4. Created AMD module example
    opened by grahamscott 6
  • Doesn't work in Internet Explorer [All versions]

    Doesn't work in Internet Explorer [All versions]

    As far as I can tell IE9+ should support the features needed to layout the word cloud. Unfortunately though it does not work out of the gates.

    I have spent some time trying to figure out why, but haven't managed to get it working properly. The problem seems to be related to the getImageData method on the canvas. My tests revealed that in IE9 it was consistently returning all zero values even after the fillText method had been called.

    Any ideas?

    opened by krisrogers 6
  • Cannot get font() to work

    Cannot get font() to work

    From the simple.html example

      ...
      d3.layout.cloud().size([300, 300])
          .words([
            "Hello", "world", "normally", "you", "want", "more", "words",
            "than", "this"].map(function(d) {
            return {text: d, size: 10 + Math.random() * 90};
          }))
          .rotate(function() { return ~~(Math.random() * 2) * 90; })
          .font('Impact')     // <!--------- DOESN'T WORK?
          .fontSize(function(d) { return d.size; })
          .on("end", draw)
          .start();
      ...
    

    Can anyone advise how to fix it?

    opened by vincenttheeten 5
  • Individual word padding/line-height removal?

    Individual word padding/line-height removal?

    Is there a way of removing/reducing the line-height or padding on the text elements?

    screen shot 2018-02-19 at 14 09 52

    The reason behind this is that I have mouseover event listener on each word which increases the font-size for the hovered text element. The problem is then trying to hover off the element, but you are still on the transparent padding, and not hitting the item behind.

    As you can see in the example above, it's nearly impossible to hit the smaller elements (note, via, etc.) around the bigger words element.

    opened by bogdancss 4
  • Overlay bug when changing layout size

    Overlay bug when changing layout size

    Here is the code that breaks for me - https://gist.github.com/StefanDimov/88a4b2a749c267ab4f78

    I want to change the layout size on window resize, so the space will be efficiently used, but sometimes when I shrink the browser's width as much as I can and then expand it some words start to layered on top of others. Doesn't occur consistently, but most of the times it's there.

    opened by StefanDimov 4
  • Need some instruction on how to get started

    Need some instruction on how to get started

    I know very little about Github so I am not sure how to get started with this library and need some very basic helps.

    1) How can I directly use this on a browser? I downloaded the zip file and extracted them to a word folder, and then under the same folder, I create a test.html file:

     <head>
      <script src="/word/build/d3.layout.cloud.js"></script>
      <script src="/word/examples/browserify.js"></script>
    </head>
    <body>
    </body>
    

    The browserify.js file will generate an error. I understand it can only be used under nodejs environment. But how can I directly use it on my webpage?

    2) How to install the library through npm? I also tried installing it on my linux server. Again, I extracted the downloaded .zip file to a word folder, and under this folder I ran npm i d3-cloud However, this is what I got: image the log says:

    verbose stack Error: Refusing to install d3-cloud as a dependency of itself

    UPDATE OK. I have been able to install the package by running npm i under the word folder. Still the question is, how can I use this library on my webpage?

    opened by newjie 0
  • Lot of space left unused

    Lot of space left unused

    version d3 : ^5.15.0 d3-cloud : ^1.2.5

    Expected behaviour All words are displayed in circles image

    Actual behaviour When changing font-size domain, lot of space left unused. image

    opened by lam612 0
  • Allow CSV import

    Allow CSV import

    To allow for much larger datasets, it would be very nice to be able to handle the 'easy part' of counting words, and let this app handle the 'hard part' of generating the graphics.

    req 
    opened by Kile-Asmussen 2
  • feature: blink words to load more?

    feature: blink words to load more?

    here is what I try to do by using jquery:

    var func = (v) => {
        $(v).css('opacity', 0)
        setTimeout(()=> {
            $(v).text(parseInt(Math.random() * 100))
            $(v).css('opacity', 1)
            setTimeout(func.bind(this, v), 3000 + Math.random() * 3000)
        },5000)
    }
    
    $('svg text').each((k, v) => {
        $(v).css('transition', 'opacity 5s cubic-bezier(0.4, 0, 0.2, 1) 0s')
        setTimeout(func.bind(this, v), Math.random() * 10000)
    })
    

    GIF 12-2 21-30-05

    req 
    opened by ycgambo 2
Create beautiful charts with one line of JavaScript

Chartkick.js Create beautiful charts with one line of JavaScript See it in action Supports Chart.js, Google Charts, and Highcharts Also available for

Andrew Kane 1.2k Nov 21, 2022
Create beautiful JavaScript charts with one line of React

React Chartkick Create beautiful JavaScript charts with one line of React See it in action Supports Chart.js, Google Charts, and Highcharts Quick Star

Andrew Kane 1.2k Nov 20, 2022
Create beautiful JavaScript charts with one line of Ruby

Chartkick Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries! See it in action Chartkick 4.0 was recen

Andrew Kane 6k Nov 24, 2022
Create PowerPoint presentations with a powerful, concise JavaScript API.

This library creates Open Office XML (OOXML) Presentations which are compatible with Microsoft PowerPoint, Apple Keynote, and other applications.

Brent Ely 1.8k Nov 26, 2022
svgMap is a JavaScript library that lets you easily create an interactable world map comparing customizable data for each country.

svgMap svgMap is a JavaScript library that lets you easily create an interactable world map comparing customizable data for each country. Live demo: h

Stephan Wagner 150 Nov 29, 2022
Create graphics with a hand-drawn, sketchy, appearance

Rough.js Rough.js is a small (<9 kB) graphics library that lets you draw in a sketchy, hand-drawn-like, style. The library defines primitives to draw

Rough 17.7k Nov 26, 2022
Matteo Bruni 4.4k Nov 21, 2022
Chart.js plugin to create charts with a hand-drawn, sketchy, appearance

chartjs-plugin-rough Chart.js plugin to create charts with a hand-drawn, sketchy, appearance Version 0.2 requires Chart.js 2.7.0 or later, and Rough.j

Akihiko Kusanagi 72 Nov 9, 2022
Using ASP.NET Core, SignalR, and ChartJs to create real-time updating charts

Real-time Charts with ASP.NET Core, SignalR, and Chart.js This project shows how to update a real-time chart in your web browser using technologies li

Khalid Abuhakmeh 11 Nov 25, 2022
JavaScript 3D library.

three.js JavaScript 3D library The aim of the project is to create an easy to use, lightweight, cross-browser, general purpose 3D library. The current

Mr.doob 87k Nov 21, 2022
Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser

Fabric.js Fabric.js is a framework that makes it easy to work with HTML5 canvas element. It is an interactive object model on top of canvas element. I

Fabric.js 23.3k Nov 20, 2022
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

Babylon.js Getting started? Play directly with the Babylon.js API using our playground. It also contains a lot of samples to learn how to use it. Any

Babylon.js 18.9k Nov 30, 2022
The JavaScript library for modern SVG graphics.

Snap.svg · A JavaScript SVG library for the modern web. Learn more at snapsvg.io. Follow us on Twitter. Install Bower - bower install snap.svg npm - n

Adobe Web Platform 13.6k Nov 29, 2022
Highcharts JS, the JavaScript charting framework

Highcharts JS is a JavaScript charting library based on SVG, with fallbacks to VML and canvas for old browsers. Official website: www.highcharts.com D

Highsoft 10.9k Nov 22, 2022
The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey

Paper.js - The Swiss Army Knife of Vector Graphics Scripting If you want to work with Paper.js, simply download the latest "stable" version from http:

Paper.js 13.4k Nov 25, 2022
JavaScript Vector Library

Raphaël: Cross-browser vector graphics the easy way Visit the library website for more information: http://raphaeljs.com https://dmitrybaranovskiy.git

Dmitry Baranovskiy 11.1k Nov 25, 2022
A JavaScript library dedicated to graph drawing

sigma.js - v1.2.1 Sigma is a JavaScript library dedicated to graph drawing, mainly developed by @jacomyal and @Yomguithereal. Resources The website pr

Alexis Jacomy 10.3k Nov 28, 2022
JavaScript diagramming library for interactive flowcharts, org charts, design tools, planning tools, visual languages.

GoJS, a JavaScript Library for HTML Diagrams GoJS is a JavaScript and TypeScript library for creating and manipulating diagrams, charts, and graphs. S

Northwoods Software Corporation 6.5k Nov 22, 2022
mxGraph is a fully client side JavaScript diagramming library

NOTE 09.11.2020 : Development on mxGraph has now stopped, this repo is effectively end of life. Known forks: https://github.com/jsGraph/mxgraph https:

JGraph 6.5k Nov 21, 2022