Advanced D3.js tutorial: Top 5 tips and tricks

Jun 18, 2021 - 9 min read
Ryan Thelin
editor-page-cover

D3.js is a JavaScript data visualization tool rapidly gaining popularity with front-end developers and data scientists. Many developers prefer D3.js over other data visualization tools because it uses web standards HTML, CSS, and JavaScript to control the appearance of charts and graphs. This allows front-end developers to jump right into data-driven analysis without having to learn a new programming language or technology.

Combine this with easy to implement animations and built-in rendering functionalities, and it’s clear why so many employers are looking for front-end developers with D3 project experience.

Today, we’ll help you stand out from other developers with 5 tips and tricks to take your D3 graphs to the next level.

Here’s what we’ll cover today:


Become a certified D3.js expert

Learn insider tips to use with each of the top D3.js chart types and earn a certificate for your resume.

D3 Tips and Tricks: Interactive Data Visualization


1. Transition Chaining

Transitions are one of the most beloved aspects of D3.js. They’re easy to implement and are widely customizable for any type of data or desired appearance. However, did you know that you can chain multiple transitions to occur sequentially from a single event?

Transition chaining allows you to implement complex animation-like transitions to add a new level of interactivity to your data. While normal transitions occur all at once, each chained transition waits for the previous transition to end before the next begins.

Chain transitions are great for showing future effects or for drawing attention to certain elements during a presentation.

To see this in action, let’s imagine we have a blue circle that we want to move to the right side of the screen, turn red, then grow in size.

<!DOCTYPE html>
<meta charset="utf-8">
 
<body>
 
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v6.min.js"></script>
 
<script>
 
var svg = d3.select("body") // Select the body element
    .append("svg")          // Append an SVG element to the body
    .attr("width", 960)     // make it 960 pixels wide
    .attr("height", 500)    // make it 500 pixels high
    .append("circle")       // append a circle to the svg
    .style("fill", "blue")  // fill the circle with 'blue'
    .attr("r", 20)          // set the radius to 10 pixels
    .attr('cx', 40)         // position the circle at 40 on the x axis
    .attr('cy', 250)        // position the circle at 250 on the y axis
    .transition()           // apply a transition
    .duration(4000)         // apply it over 4000 milliseconds
    .attr('cx', 850)        // new horizontal position at 850 on x axis
    .attr('r', 40)          // new radius of 40 pixels
    .style('fill', "red");  // new colour red
 
</script>
</body>

This transition code meets all our criteria but it is not chained. All transitions will occur at once.

To make the transitions execute one at a time, we’ll need to tweak our code to match the following:

<!DOCTYPE html>
<meta charset="utf-8">
 
<body>
 
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v6.min.js"></script>
 
<script>
 
var svg = d3.select("body") // Select the body element
    .append("svg")          // Append an SVG element to the body
    .attr("width", 960)     // make it 960 pixels wide
    .attr("height", 500)    // make it 500 pixels high
    .append("circle")       // append a circle to the svg
        .style("fill", "blue")  // fill the circle with 'blue'
        .attr("r", 20)          // set the radius to 10 pixels
        .attr('cx', 40)         // position the circle at 40 on the x axis
        .attr('cy', 250)        // position the circle at 250 on the y axis
    // 1st transition
        .transition()           // apply a transition
        .duration(4000)         // apply it over 4000 milliseconds
        .attr('cx', 830)        // new horizontal position at 830 on x axis
    // 2nd transition
        .transition()           // apply a transition
        .duration(4000)         // apply it over 4000 milliseconds
        .attr('r', 40)          // new radius of 40 pixels
    // 3rd transition
        .transition()           // apply a transition
        .duration(4000)         // apply it over 4000 milliseconds
        .style('fill', "red");  // new colour red
 
</script>
</body>

Our transition now executes in three distinct steps:

1 of 3

2. Adding web links to a D3.js object

A single graph can rarely tell the full story. Sometimes it’s beneficial to include click-through links on elements that can bring the user to a deeper exploration of the specific topic. Web links are best used to allow users to naturally explore the data or to give access to extra resources that may help them understand your graph.

For example, your graph may include an element that represents all front-end developers. It could also have a link to another page that shows a robust breakdown of each type of front-end developer within the larger category.

To do this, we’ll need the <a> tag and the xlink keyword. The <a> tag in an HTML file defines a hyperlink. Items surrounded by an <a> tag will become a link to another web address. So what we will do is create an <a> tag and then append our D3.js and SVG object to it.

Of course, as well as including a link, we need to tell it where to go. We do this by setting the xlink:href attribute for our tag to point to a specific page. Xlink is short for XML Linking Language, and it is used to create hyperlinks in XML documents. In our case, we will be defining the link that we will want our user to go to.

Instead of linking both the text and rectangle to the link, we’ll make the program ignore the text and only interact with the rectangle element. We can do this using the pointer-events style when drawing our text. By setting it to none, we are instructing our mouse to ignore any potential interaction with the text when it hovers over it and instead the pointer will register the link on the rectangle below it.

<!DOCTYPE html>
<meta charset="utf-8">

<body>

<!-- load the d3.js library -->	
<script src="https://d3js.org/d3.v6.min.js"></script>

<script>
 
var width = 449;
var height = 249;
var word = "frontend";
 
var holder = d3.select("body")
      .append("svg")
      .attr("width", width)    
      .attr("height", height); 

// draw a rectangle
holder.append("a")
    .attr("xlink:href", "http://en.wikipedia.org/wiki/"+word)
    .append("rect")  
    .attr("x", 100)
    .attr("y", 50)
    .attr("height", 100)
    .attr("width", 200)
    .style("fill", "lightgreen")
    .attr("rx", 10)
    .attr("ry", 10);

// draw text on the screen
holder.append("text")
    .attr("x", 200)
    .attr("y", 100)
    .style("fill", "black")
    .style("font-size", "20px")
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .style("pointer-events", "none")
    .text(word);

</script>

</body>
Functional "frontend" element with link
Functional "frontend" element with link

3. Including HTML tables with your graph

D3 is most often used to create graphs and charts, but it’s capable of rendering HTML tables as well. You can add a table by itself or alongside your graph. Including a table with your graph allows your users to get a closer look at each data point and learn the exact values that make up the graph.

HTML tables are made up of rows, columns, and data that goes in each cell. All you need to do to successfully place a table on a web page is to lay out the rows and columns in a logical sequence using the appropriate HTML tags.

For example, take a look at the HTML code below to see a simple table implementation:

HTML:

<!DOCTYPE html>
<body>
    <table border="1">
        <tr>
            <th>Header 1</th>
            <th>Header 2</th>
        </tr>
        <tr>
            <td>row 1, cell 1</td>
            <td>row 1, cell 2</td>
        </tr>
        <tr>
            <td>row 2, cell 1</td>
            <td>row 2, cell 2</td>
        </tr>
    </table>
</body>

Result:

The entire table itself is enclosed in <table> tags. Each row is enclosed in <tr> tags. Each row has two items, which equate to the two columns. Each piece of data for each cell is enclosed in a <td> tag, except for the first row, which is a header. A header has a special tag <th> that sets it to be bold and centered.

For ease of viewing, we have told the table to place a border around each cell, and we do this in the first <table> tag with the border="1" statement.

Now, let’s add an HTML table under a D3 graph. Lines 77-114 create our table.

index.html
data.cvs
date,close
1-May-12,58.13
30-Apr-12,53.98
27-Apr-12,67.00
26-Apr-12,89.70
25-Apr-12,99.00
24-Apr-12,130.28
23-Apr-12,166.70
20-Apr-12,234.98
19-Apr-12,345.44
18-Apr-12,443.34
17-Apr-12,543.70
16-Apr-12,580.13
13-Apr-12,605.23
12-Apr-12,622.77
11-Apr-12,626.20
10-Apr-12,628.44
9-Apr-12,636.23
5-Apr-12,633.68
4-Apr-12,624.31
3-Apr-12,629.32
2-Apr-12,618.63
30-Mar-12,599.55
29-Mar-12,609.86
28-Mar-12,617.62
27-Mar-12,614.48
26-Mar-12,606.98
Graph with HTML table beneath
Graph with HTML table beneath

Keep the learning going.

Transition to D3.js, the best data visualization tool for front-end developers. Educative’s text-based, hands-on courses help you learn the latest technologies in half the time.

D3 Tips and Tricks: Interactive Data Visualization


4. Toggling Show/hide graph elements with a click

The best graphs include options for users to explore the data from both a big picture and a detailed view.

One easy way to do this is to allow users to hide certain data points to get a closer look at relationships or trends. The more data points you have on the same graph, the more useful this function becomes!

Let’s create a sample line graph that allows you to toggle the visibility of each line by clicking the graph legend at the bottom.

Sample Line Graph
Sample Line Graph

There are two main parts to implementing this technique. Firstly, we have to label the element (or elements) that we wish to show/hide with a click. Then, we have to give the clickable object an attribute that allows it to recognize a mouse click and then execute the code to show/hide our labeled element.

Here’s how we’d implement these steps into D3.js:

index.html
data4.csv
data.csv
date,close,open
1-May-12,58.13,3.41
30-Apr-12,53.98,4.55
27-Apr-12,67.00,6.78
26-Apr-12,89.70,7.85
25-Apr-12,99.00,8.92
24-Apr-12,130.28,9.92
23-Apr-12,166.70,10.13
20-Apr-12,234.98,12.23
19-Apr-12,345.44,13.45
18-Apr-12,443.34,16.04
17-Apr-12,543.70,18.03
16-Apr-12,580.13,21.02
13-Apr-12,605.23,22.34
12-Apr-12,622.77,20.15
11-Apr-12,626.20,21.26
10-Apr-12,628.44,31.04
9-Apr-12,636.23,35.04
5-Apr-12,633.68,41.02
4-Apr-12,624.31,43.05
3-Apr-12,629.32,46.03
2-Apr-12,618.63,51.03
30-Mar-12,599.55,53.42
29-Mar-12,609.86,57.82
28-Mar-12,617.62,59.01
27-Mar-12,614.48,56.03
26-Mar-12,606.98,58.01
1 of 3

The explanation below explores how we can change the blueline to be togglable.

To label the element, add an id attribute to an element that identifies it uniquely. We’ll use this to hide just one element but not others.

  • Lines 81-85: In the example above, we have applied the id blueLine (line 84) to the path that draws the blue line on our graph.

  • Lines 112-126: The second part is a little trickier. The following is the portion of JavaScript that places our text label under the graph. The only part of it that is unusual is the .on("click", function() section of the code.

    When we click on our blue line text element, the .on("click", function() section executes.

  • Lines 119-120: We’re using a short-hand version of the if statement a couple of times here. Firstly, we check to see if the variable blueLine.active is true or false. If it’s true, it gets set to false, and if it’s false, it gets set to true. In other words, it flips the Boolean with each click.

    Then after toggling this variable, we set the value of newOpacity to either 0 or 1, depending on whether active is true or false at the second short-hand JavaScript if statement.

  • Line 122: We can then select our identifiers that we have declared using the id attributes in the earlier pieces of code and modify their opacity to either 0 (off) or 1 (on)

  • Line 124: Lastly, we update our blueLine.active variable to whatever the active state is so that it can toggle correctly the next time it is clicked on.


5. Filtering using an if statement

Instead of hiding elements, you may want to highlight certain data points base on defined criteria. This is helpful when parsing large data sets for outliers or data beyond a certain threshold, such as those that take place on a particular date.

D3.js allows you to do this by including standard JavaScript if statements during graph creation. For example, consider we wanted to create a scatter plot that highlights all points with a value greater than 300.

  // Add the scatterplot
  svg.selectAll("dot")
      .data(data)
    .enter().append("circle")
      .attr("r", 5)
      .style("fill", function(d) {            // <== Add these
          if (d.close <= 400) {return "red"}  // <== Add these
          else { return "black" }             // <== Add these
      ;})                                     // <== Add these
      .attr("cx", function(d) { return x(d.date); })
      .attr("cy", function(d) { return y(d.close); });
  • Lines 6-7 set fill to be decided based on the value of the datapoint.
  • The end of line 7 checks if the value of the data point is less than 400 and sets fill to red if true.
  • If the data point is greater than 400, line 8 executes and sets fill to black.
Black highlights on values greater than 400
Black highlights on values greater than 400

You can also set multiple if filters to further customize your graph.

  // Add the scatterplot
  svg.selectAll("dot")
      .data(data)
    .enter().append("circle")
      .attr("r", 5)
      .style("fill", function(d) {
         if (d.close <= 400) {return "red"}
         else if (d.close >= 620) {return "lawngreen"} // <== Right here
         else { return "black" }
      ;})
      .attr("cx", function(d) { return x(d.date); })
      .attr("cy", function(d) { return y(d.close); });

The else-if statement on line 8 sets an additional filter to look for data points that are greater than or equal to 620.

Points greater than 400 are black and points greater than 620 are green
Points greater than 400 are black and points greater than 620 are green

What to learn next

Tips and tricks like these make the difference between a D3.js developer and a master. Each of these will make your graphs more comprehensive and interactive, allowing you to better serve the needs of your users.

However, there are many more D3.js tricks you can use to optimize your projects. Other D3 features to learn next are:

  • Interactive element placement/rotation
  • Image exports
  • Implementing user input
  • JSON integration

To help you learn these and more D3.js tricks, Educative has created the course D3 Tips and Tricks: Interactive Data Visualization. This course explores all the most used chart types, providing insider tips on what attributes will be most important for each and how to implement them. By the end of the course, you’ll have completed dozens of hands-on exercises and have a certificate to add to your resume.

Happy learning!


Continue reading about D3.js and JavaScript


WRITTEN BYRyan Thelin

Join a community of 500,000 monthly readers. A free, bi-monthly email with a roundup of Educative's top articles and coding tips.