D3 Word Cloud with Create React App
Published: May 10, 2019
Last updated: May 10, 2019
Initialise CRA App
First of all, initalise the React app:
create-react-app d3-wordcloud && cd d3-wordcloud
Install D3 Deps
For this particular case, we want to install a particular set of D3 libs:
yarn add d3-scale d3-cloud d3-selection
Setting Up Our Data Stub
For simplicity sake, let's create a JSON set of data that we can use to pass down into our final component.
In the src
directory, let's create data.json
and add the following data:
{ "data": [ { "text": "frequency", "frequency": 63 }, { "text": "function", "frequency": 61 }, { "text": "data", "frequency": 47 }, { "text": "return", "frequency": 36 }, { "text": "attr", "frequency": 29 }, { "text": "chart", "frequency": 28 }, { "text": "array", "frequency": 24 }, { "text": "style", "frequency": 24 }, { "text": "layouts", "frequency": 22 }, { "text": "values", "frequency": 22 }, { "text": "need", "frequency": 21 }, { "text": "nodes", "frequency": 21 }, { "text": "pie", "frequency": 21 }, { "text": "use", "frequency": 21 }, { "text": "figure", "frequency": 20 }, { "text": "circle", "frequency": 19 }, { "text": "we'll", "frequency": 19 }, { "text": "zoom", "frequency": 19 }, { "text": "append", "frequency": 17 }, { "text": "elements", "frequency": 17 } ] }
We will import this JSON and pass it down to create the final file.
Updating App.js
Now, let's update our App.js
from it's initial state to the following:
import React, { Component } from "react"; import logo from "./logo.svg"; import "./App.css"; import WordCloud from "./WordCloud"; import wordData from "./data.json"; class App extends Component { render() { return ( <div className="App"> <WordCloud id="wcloud" w="600" h="600" data={wordData.data} threshold={25} /> </div> ); } } export default App;
There are some important steps to note from what we just did:
- We imported the data from
data.json
- We imported our
WordCloud
component from theWordCloud.js
file - We add properties
id
,w
,h
,data
andthreshold
- we will explore these properties a little bit later.
If you try running the app at the moment, it will evidently fail given we haven't created the WordCloud.js
file - so let's do just that.
Creating the WordCloud
With the src
folder, let's create a WordCloud.js
file.
Let's fill out the WordCloud.js
file with the following:
import React, { Component } from "react"; import { scaleLinear } from "d3-scale"; import cloud from "d3-cloud"; import { select } from "d3-selection"; /** * A D3 reusable Word Cloud * * @example * // sample usage with import * <WordCloud id="wcloud" w="600" h="600" data={wordData.data} threshold={25}/> * * @class WordCloud * @extends {Component} */ class WordCloud extends Component { componentDidMount() { this.drawChart(); } drawChart() { const { id, w, h, data, threshold = 20 } = this.props; const wordScale = scaleLinear().domain([0, 75]).range([10, 120]); const randomRotate = scaleLinear().domain([0, 1]).range([-20, 20]); cloud() .size([500, 500]) .words(data) .rotate(() => randomRotate(Math.random())) .rotate((d) => (d.text.length > 5 ? 0 : 90)) .fontSize((d) => wordScale(d.frequency)) .on("end", draw) .start(); function draw(words) { const svg = select("#" + id) .append("svg") .attr("height", h) .attr("width", w) .append("g") .attr("id", "wordCloud") .attr("transform", `translate(${w / 2},${h / 2})`); svg .selectAll("text") .data(words) .enter() .append("text") .style("font-size", (d) => d.size + "px") .style("fill", (d) => (d.frequency > threshold ? "#fe9922" : "#4f442b")) .attr("text-anchor", "middle") .attr("transform", (d) => `translate(${[d.x, d.y]})rotate(${d.rotate})`) .text((d) => d.text); } } render() { return ( <div id={this.props.id} style={{ width: this.props.w, height: this.props.h, }} /> ); } } export default WordCloud;
What you'll note here is that our render
function returns ONLY a div that will have a few properties to define the id
and width
and height
style properties.
Secondly, we have an componentDidMount
method that calls our drawChart
function - this is important for appending our required SVG elements.
Thirdly, our drawChart
function makes use of each of our props with a default value of 20 for threshold
.
Our chart should now be up and looking pretty!
D3 WordCloud
Bam - our JSON data is defining the words required for the cloud and the colour is being determined by threshold
parameter that we are using. Play around with this threshold to update the colour or remove it to use the default value of 20!
This is just a simple word colour. You could change the colour function or play around with it however you want from here.
D3 Word Cloud with Create React App
Introduction