Bubble Chart in D3js
Tags: SVG, Web Development, D3js, JavaScript, Data Visualization

How a bubble chart looks like

From Wikipedia, a bubble chart show the relationship between three variables.

Version 6

Why 6?

At this time is the latest stable version of d3. To me it is more compacted, you have more functions in its core and is easier to load its modules…

I leave you the link anyway for installing it in different environments

https://github.com/d3/d3#installing

But, I love npm so if you are like me …

$ npm i d3

Then, in you load in your js

index.js

import * as d3 from "d3";

Dataset

We are going to create something similar, now imagine you have a similar dataset

const dataset = [

{ type: "Sample 1", value: 50, radius: 7 },

{ type: "Sample 2", value: 30, radius: 11 },

{ type: "Sample 3", value: 10, radius: 3 }

];

But, first of all a couple of utility function in d3 to manipulate data

d3.extent to calculate min and max

d3.extent(dataset, d => d.value) ==> [10, 50]

However, our Y Axis starts at 0 so we can only use d3.max function and finish with 60.

d3.max(dataset, d => d.value) + 10 ==> 60

Moreover, we need an array with all the ordinal values so we can use map function from es6 or mapping from d3 that extracts the names.

dataset.map(d => d.type) ==> ["Sample 1", "Sample 2", "Sample 3"] d3.map(dataset, d => d.type).keys() ==> ["Sample 1", "Sample 2", "Sample 3"]

As you see d3 has some native functions over arrays that can be very useful.

Svg

It is always the same, create a frame with margin, the width & height of the content, translating it correctly to visually /display correctly and so on and so forth…

index.html

<div id="viz"></div>

index.js

const margin = { top: 40, right: 150, bottom: 60, left: 30 },

width = 500 - margin.left - margin.right,

height = 420 - margin.top - margin.bottom; const svg = d3

.select("#viz")

.append("svg")

.attr("width", width + margin.left + margin.right)

.attr("height", height + margin.top + margin.bottom)

.append("g")

.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

Axis and Scale

For X Axis we have to create and scale of discrete values equally distributed along the axis

index.js

const types = dataset.map(d => d.type); ==> ["Sample 1", "Sample 2", "Sample 3"] // Add X scale const x = d3

.scaleBand()

.domain(types)

.range([0, width]); // Add X axis svg

.append("g")

.attr("transform", "translate(0," + height + ")")

.call(d3.axisBottom(x));

At this point, you may wonder why I use scaleBand rather than scaleOrdinal ???

scaleOrdinal maps discrete values (specified by an array) to discrete values (also specified by an array)

And

In scaleBand domain is specified as an array of values (one value for each band) and the range is splitted automatically into n bands computing the positions and widths of them.

So basically with scaleBand we specify less and we get part of the job done automatically

X Axis and X Scale that we have created with the code below

For understanding scales, another amazing resource is

https://www.d3indepth.com/scales/

For Y Axis we create a linear scale from 0 to the maximum value of values

index.js

const yMax = d3.max(dataset, d => d.value) + 10 ==> 60 // Add Y scale const y = d3

.scaleLinear()

.domain([0, yMax])

.range([height, 0]); // Add Y axis svg.append("g").call(d3.axisLeft(y));

Axis and Scales that we have created with the code below

Bubbles

For Bubbles we create circles using radius value in dataset for size and positioning them with its type and value. Normally, things used to be more complex with a customized scale in radius and colorized bubbles.

index.js

// Add bubbles svg

.append("g")

.selectAll("bubble")

.data(dataset)

.enter()

.append("circle")

.attr("cx", d => x(d.type) + 50)

.attr("cy", d => y(d.value))

.attr("r", d => d.radius)

.style("fill", "lightcyan")

.style("opacity", "0.7")

.attr("stroke", "black");

Result

Here it is our basic Bubble Chart

Code

Conclusions

You can play with it, changing a lot of things and customize colors, axis, etc.

If you start with dataviz and d3js, try to go deeper understanding every thing you do. It is a hard task at the beginning, but there are a lot of resources and step by step you can do amazing things.

Thanks for reading.