Making a d3.js scatter-plot interactive-part one

Sabahat Iqbal
4 min readJun 11, 2020

--

This tutorial explains how to add interactivity to a scatter-plot that was built in an earlier tutorial. As a reminder, this is what the data structure looks like:

Poverty Rate is the y-axis value and the indicator in the last column is the x-axis value and changes with each dataset.

This tutorial will explain how to update Province. The final code can be viewed here.

There are two important aspects in building user interactivity:

  1. Capturing the user’s choice.
  2. Updating the page based on user’s choice.

As a reminder, the focus of this tutorial is d3.js so coverage of other topics will be minimal.

Capturing The User’s Choice

  • Add a select HTML tag with options for each of the province names and one for “All Provinces”.
Drop-down to capture user’s choice.

Updating The Page Based On User’s Choice

  • Filter inputted data (argument to updateChart ) and return new dataset based on user’s Geographic Choice.
function updateChart(someData) {
let dataAdultLit = d3
.nest()
.key(function (d) {
return d[“Year”];
})
.entries(someData[0]);
let filteredData = dataAdultLit[5]; //Note update here; important!filteredData =
$(“#geographicChoice”).val() === “allProv”
? filteredData[“values”]
: filteredData[“values”].filter(
(each) => each[“Province”] === $(“#geographicChoice”).val()
);
  • Upon initial page load, $(“#geographicChoice”).val() === “allProv” will be true because that is the default value of the dropdown and user has not changed it.
  • Once the user selects a new choice, updateChart will have to be re-triggered. Add the following code in after initial data load function:
//Add in event listener for geographic choice.
$(“#geographicChoice”).on(“change”, function () {
updateChart(allData);
});
  • If you console.log(filteredData) in updateChart, you will see that the data is updating as user makes different choices. This is where d3 (finally) comes in. We have to “call” all the items in the chart we want updated (circles in scatter-plot, in this case) and “instruct” them to change based on the new data.

Exit, Update, Enter

This is a tough d3 concept and I have to think it through each time I use it.

  • Important reminder: d3 works because we attach one row of data per SVG element (like a circle or a rectangle). The attributes of the SVG element, such as radius, length, width are determined by various datum within that row of data. When the data changes (because, for example, user chose a different province), then the datum changes, and so the attributes of the SVG element changes. Enter, Exit, Update is the way for the SVG elements to reflect the initial data and then to reflect the updated data. As per previous tutorial, the first step is to attach — or join — data to SVG elements.
  • Now, we want to update the SVG elements so we have to take in the new data (based on user choice), remove any no-longer-necessary SVG elements, and update existing SVG elements. In this case, when a user selects a province, we have to remove data for all other provinces and update chart to match selected province. This is a rough outline of the process:
  • Join updated data to SVG element:

// JOIN new data with old elements.
var circles = svg.selectAll(“circle”).data(filteredData, function (d) {
return d[“District”];
});

  • Exit: after joining to the updated data, remove any SVG elements (i.e. circles) that became unnecessary.

// EXIT old elements not present in new data.
circles.exit().remove();

  • Enter: use the updated dataset to create the circles.
// ENTER new elements present in new data.
circles
.enter()
.append(“circle”)
.attr(“class”, “enter”)
.attr(“fill”, function (d) {
return color(d[“Province”]);
})
.attr(“cy”, function (d) {
return y(d[“Poverty Rate (%)”]);
})
.attr(“cx”, function (d) {
return x(
d[
“Adult literacy, 25 or more years old (% of population aged 25 or more)”
]
);
})
.attr(“r”, 5);
  • Update: at this point, because we are not doing anything with the circles that already exist in the scatter-plot, we can skip the update selection. We are only removing old unwanted circles (think Districts)and then (possibly, depending on that specific user choice) adding in new circles (again, think Districts). We would need update selection if, for example, there was a circle on the page that represented District X which had values of (5,10) for the x,y attributes but after the data is updated, District X data changes so that x,y attributes have the values (0,15). In this case, exit wouldn’t do anything because I want to keep the data point, i.e that District. enter wouldn’t help because District X was already on the page. So I need to use update to move the circle over.

If anyone runs through this tutorial, please let me know what you think especially if any concept is still confusing. I would love to hear from you.

Next tutorial: how to use update selection to move existing circles around. Why would we want to do that? If we have a bunch of circles representing a bunch of districts for the year 2004 but now want to show the same districts in the year 2014, we have to use the update selection.

--

--