DJDMorrison

Animated Word Cloud

Built with D3 and D3-Cloud

Live Demo
Javascript

Sat Nov 27 2021

A feature request at work that turned into a dive into D3 and data visualization. Each time a word is added, the cloud will recalculate it's layout and transition each element to it's new size and position.

At work we wanted to introduce a new social feature; a live poll that allows users to submit words which are then visualized on a word cloud. This is a fairly simple visualization - the higher the frequency that a word appears in the resulting list, the larger the word and the more central it is. However, the ask here was that each time a word is submitted the cloud will recalculate the positions and display an updated cloud to the users.

Research

After a bit of googling and research I found there aren't many packages for creating word cloud, at least built for Angular (our framework of choice). The most popular seemed to be a D3.js plugin named d3-cloud by jasondavies. d3-cloud has a number of exposed functions that suit a number of use cases and thankfully it covered all our needs.

Having never used D3 it took a bit of time to become familiar with how to properly use it, but it's fairly well documented and there's a number of examples online with a quick search. One very useful website was D3.js Graph Gallery which offers examples with editable code for quick prototyping.

D3 - Binding Elements to Data

One extremely powerful feature I found in D3 is the ability to bind elements to pieces of data. Say I have a list of elements, and each element should be represented by a paragraph tag. If I make a change to one of the elements, the linked paragraph tag will update.

An example from the D3 website (Under Dynamic Properties) has the following code:

d3.selectAll("p")
  .data([4, 8, 15, 16, 23, 42])
  .style("font-size", x => `${x}px`);

The above will bind each element in the data array to a paragraph element. The paragraph element's font-size will then be determined by the element's value.

If an element is then updated in the data array, the paragraph's font-size will be updated without having to add/remove elements from the DOM.

D3 - Transitions

The next D3 feature that helped with the word cloud requirement was being transitions. When an element is updated and it's font size or transform attributes have changed, the transition function allows you to smoothly move between the old and new state.

Combining this with binding elements to data meant that a word can be binded to a text element and each time the word's properties change it can simply transition to it's new size or position within the word cloud.

Calculating Word Sizes

Once I was comfortable with the code to create a basic word cloud, the next task was to create a function that would determine the size of each word.

As before, the size of the word is determined by it's frequency in the data set, higher frequency = larger size. This took a suprising amount of thought but it basically boiled down to determining the unique counts of all the words (e.g. if the data set is ['a', 'a', 'b', 'b', 'c'] the unique counts will be [2, 1]), creating a scale of sizes based on how many unique counts there are, between a maximum and minimum size, and then assigning each word it's size based on it's count.