~ / teaching / InfoVis / practical works / Interactive BubbleChart

Interactive BubbleChart with D3.js

© 2022— - Renaud Blanch

The goal of this practical work is to build a first interactive visualisation using D3.js with data having more than 2 attributes, using the position, color, and size visual variables.

You will build a clone of the BubbleChart used by GapMinder to show development indicators.

Setup

Get the archive that contains the dataset; the version of D3.js that you are going to use; and a visualisation template. Unzip it and get used to its content.

The data/gapminder directory contains an excerpt of the datasets that are made available by GapMinder (see the README.md for licence details):

The vendor directory contains the D3.js version 7.8.5 code.

The viz directory contains a visualisation template that produces an HTML numbered list of the top-20 countries, according to their GDP, for the year selected with a dropdown menu.

To test this template, you need to start a web server. The simplest way to go is using python in a terminal as shown below:

% tar xzvf gapminder.tgz
x gapminder/data/
[...]
x gapminder/vendor
[...]
x gapminder/viz/
x gapminder/viz/gapminder.html
% cd gapminder/
% python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 ...

You can then open in a new tab your local version of the visualisation that should display the country list, as the online version does.

Bubble Chart

The first step consists in creating the bubbles using a visual mapping that will project each item for a chosen year (e.g., 2019) onto a mark (circle):

The sample visualisation (lines 17-50) shows how to load and merge data from multiple files. For each country, create a SVG group that has a translation as transform attribute and choose the translation according to data of the country. Then add a circle element to this group.

For the horizontal axis, given the distribution of the income data, a log scale is more appropriate than a simple linear mapping. For the size attribute, a square root scale is appropriate, because we want the population mapped onto the surface of the circles (rather than their radius).

In order to prevent occlusion of small circles by large circles, the data must be sorted according to the population attribute before creating the circles.

When this first step is completed, the visualisation should look like this:

The second step consists in adding some decorations:

To change the position and the values of those cursors when the user hovers a bubble, add a listener to the groups representing the countries that will get called upon 'mouseenter' events by D3's event handling mechanism.

The third step consists in setting attributes of bubbles that depend on countries details:

The title element is handled by the browser to add a tooltip when hovering the SVG elements as shown on the capture below:

Interactions

The first interaction consists in adding a legend for the regions that users can click to alternatively show or hide the bubbles corresponding to the actioned item of the legend. To do so,

On the capture below, Europe is deselected and the corresponding bubbles have their opacity set to .1:

The next interaction consists in adding an interactive slider to select the year displayed on the visualisation. One possibility for making a slider is to:

Once this is done, we need to handle the interaction. For that we can use D3's support for drag behavior to add a listener to the 'drag' event that will:

At this point, the slider should work, but the bubbles need to be updated to represent the data of the selected year. To do so, you should:

Animations

In this part you will add animations to the visualisation.

The first animation will step through the years and change accordingly the visualisation. To do so:

The animation can be stepped through using the d3.interval function that repeatedly invokes a callback at specified interval (e.g., advance a year every 120ms). It can call a step_year() function that will find the next year to display (given the current year that you may need to store in a variable) and call set_year(year) accordingly.

Special attention should be payed to the stopping conditions for the animation: the user may click the play/pause button; the animation may reach the end of the year scale; or the user may grab the year slider's thumb to choose a year.

To make the animation smoother, use the selection.transition() mechanism to animate the bubbles radius and positions when they are updated for a new year. The duration of the animation may be different when the change comes from the animation, or from an interaction with the slider. Adding a duration parameter to the set_year and set_data functions could help with that.

The visualisation should now look something like that:

Bonus

Transform the region legend to add a map of the regions (see shape_lores_svg attribute of the regions dataset). The regions should be clickable to show/hide the corresponding bubbles.

Add a legend for the population. This legend should also display the population of the current country.

last update: dec. 8, 2022