DEV Community

ayka.code
ayka.code

Posted on

Creating Interactive Charts with D3.js

Original post with codepen representation: Creating Interactive Charts with D3.js

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>
<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>

Enter fullscreen mode Exit fullscreen mode

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:

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

Enter fullscreen mode Exit fullscreen mode

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:

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

Enter fullscreen mode Exit fullscreen mode

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:

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')

Enter fullscreen mode Exit fullscreen mode

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.

.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)`)

Enter fullscreen mode Exit fullscreen mode

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:

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)`)

Enter fullscreen mode Exit fullscreen mode

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:

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

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

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. Happy coding!

Top comments (0)