Creating Interactive Charts with D3.js
Aymen kani|January 3rd 2023

D3 (short for Data-Driven Documents) is a JavaScript library that allows you to create interactive data visualizations for the web. With D3, you can create a wide range of visualizations, from simple charts and graphs to complex interactive graphics.

In this tutorial, we'll look at how to create a simple bar chart using D3. We'll start with a basic bar chart, and then add interactivity to it by updating the chart data and labels when the user hovers over a bar.

First, let's set up the HTML for our chart. We'll include a div element with an id of "chart", and a script tag to include the D3 library:

html

<html>
<head>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
      body {
        overflow: scroll;
      }
      #chart {
        display: grid;
        grid-template-columns: 1fr;
        height: 100vh;
        width: 100vw;
        justify-items: center;
        align-items: center;
      }
    </style>
</head>
<body>
<div id="chart"></div>
<script>
 <!-- the chart logic goes here! -->
</script>
</body>
</html>

Next, let's define the data for our chart. We'll use an array of objects, with each object representing a bar in the chart. Each object should have a name and value property:

javascript

const data = [
  { name: 'Alice', value: 100 },
  { name: 'Bob', value: 75 },
  { name: 'Eve', value: 50 },
  { name: 'Mike', value: 0 }
];

Now, let's set up the SVG element that will contain our chart. We'll specify the width and height of the chart, as well as the padding between the bars. We'll also define a scale for the x-axis, which will determine the width of each bar:

javascript

const height = 300;
const barPadding = 10;
const barWidth = 30;

const xScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)]) //from 0 to the greatest value (100)
  .range([0, width]); // make the width of the svg fit the chart

const yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)])
  .range([height, 0]);

const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);

const svg = d3
  .select('#chart')
  .append('svg')
  .attr('width', width+35)// add 35 to fit the xAxis
  .attr('height', height+35) // add 35 to fit the yAxis

Now, let's create the bars for our chart. We'll use theĀ rect element to create the bars, and bind our data to them using theĀ data function. We'll also specify the x and y positions of the bars, as well as their width and height:

javascript

svg
  .selectAll('rect')
  .data(data)
  .enter()
  .append('rect')
  .attr('x', (d, i) => i * (barWidth + barPadding))
  .attr('y', (d) => yScale(d.value))
  .attr('width', barWidth)
  .attr('height', (d) => height - yScale(d.value))
  .attr('fill', '#2196f3')

Next, let's add interactivity to our chart. We'll add a mouseover and mouseout event to the bars, and update the chart data and labels when the user hovers over a bar.

javascript

.on('mouseover', function(d, i) {  // Add a mouseover event to the bars
  d3.select(this).style('opacity', 0.5);// change opacity
  svg
    .selectAll('text')
    .filter((d, j) => d===i)// select the text related to the bar
    .text(i.name);  // Change the text from value to name
})
.on('mouseout', function(d, i) {  // Add a mouseout event to the bars
  // reverse everything
  d3.select(this).style('opacity', 1);
  svg
    .selectAll('text')
    .filter((d, j) => d===i)
    .text(i.value); 
})
.attr('transform', `translate(25, 10)`)

Now, let's add the labels for our chart. We'll use theĀ text element to create the labels, and bind our data to them using theĀ data function. We'll also specify the x and y positions of the labels:

javascript

svg
  .selectAll('text')
  .data(data)
  .enter()
  .append('text')
  .text((d) => d.value)
  .attr('x', (d, i) => i * (barWidth + barPadding) + barWidth / 2)
  .attr('y', (d) => yScale(d.value) )
  .attr('text-anchor', 'middle')
  .attr('font-size', '14px')
  .attr('fill', 'black')
  .on('mouseover', function(d, i) {  // Add a mouseover event to the text

    // this: refers to the text. this.parentNode: refers to the whole SVG
    d3.select(this).text(i.name); // change text from value to name

  })
  .on('mouseout', function(d, i) {  // Add a mouseout event to the text
    d3.select(this).text(i.value);
  })
  .attr('transform', `translate(25, 10)`)

Finally, let's add the x and y axes to our chart. We'll use the g element to group the x and y axes, and the call function to render them:

javascript

svg
  .append('g')
  .attr('transform', `translate(25, ${height+10})`)
  .call(xAxis);

svg
  .append('g')
  .attr('transform', `translate(25, 10)`)
  .call(yAxis);

And that's it! You now have a fully interactive bar chart using D3.js.

It's worth noting that there are many libraries out there that can create charts and graphs for you, such as Chart.js, Highcharts, and Google Charts. However, D3.js offers a lot of flexibility and customization options, allowing you to create exactly the chart you need for your web application.

I hope this tutorial has helped you get started with creating interactive charts using D3.js. As always, if you have any questions or need further guidance, don't hesitate to ask: Twitter. Happy coding!

D3.js interactive charts data visualization JavaScript bar charts scatter plots web application customization data binding x-axis y-axis