Flexible Data Visualization with D3 Bar Chart

D3 horizontal bar graph with X & Y axis defined and color bars

Last Updated on August 11, 2024 by E. Scott

Creating a D3 bar chart begins as many others do. Chartjs, NVD3, D3, or even High Charts I believe, begin with either a canvas tag or an SVG element. That’s exactly what’s happening here. The SVG element is then wrapped in D3’s selector. Upon which, a whole host of methods make themselves available.

Data visualizations are used for a variety of needs. Just to name a few…

  • Data powered dashboards
  • Analytics
  • Finance platforms
  • Software that checks for API status’, sales, etc.
Multiple variations of a D3 Bar Chart with different data, color, and features.

D3 Bar Chart Comparison

Chart.js is a JavaScript library used to create charts. Chart types include but are not limited to bar, line and pie, radar, doughnut, polar, area, bubble, and scatter charts. Users have the ability to represent data in multiple formats. Users can customize charts tremendously via color, labels, tool tips, and even animation. Moreover, they’re natively responsive.

NVD3 is a library built on top of D3. Intended on simplifying the process while still harnessing the power of D3. It’s open source and therefor free to use. It can be integrated easily but of course requires D3 as a dependency.

High Charts is also a JavaScript library designed to create interactive and responsive data visualizations. Their arsenal is comprised of line, spline, area, column, bar, pie, scatter, and many more. Perhaps most impressively, multiple charts can be combined into one. This is a library that offers far more features than competitors’. Multitouch support, multiple axes support, configurable tool tips, and the ability to export in multiple formats. A license is required for commercial usage.

multiple d3 chart types with different data, colors, and animation.

D3 on the other hand is quite different. D3 offers the highest level of customization.

  • Data can be bound directly to DOM elements allowing devs to create custom chart types and layouts.
  • Supports a very wide range of chart types, providing extensive flexibility.
  • D3 is very popular and in turn has a large community with comprehensive docs. There’s an abundance of tutorials.
  • Very efficient in handling large data sets due to its data binding abilities. This D3 bar chart is but one example.
  • This is a standalone library with zero external dependencies.

Git Repo

Markup and Styling

Nothing over the top with the CSS. Pretty generic stuff. At the bottom though, notice the SVG tag wrapped in the graph-wrapper. That’s what we’re targeting. The SVG is the entire graph.

My opinion is, if you’re gonna learn NVD3, you may as well learn the underlying library itself. I’ve found it to be easier to use in some versions of UI frameworks.

And once you get the hang of it, it’s a pleasure to work with outside of frameworks. Which is unfortunately not too frequently. The complexity however gives devs fine grain control over literally everything imaginable. So learning it definitely has it’s advantages. Namely in the era of data visualization UIs we’re currently in.

#graph-wrapper {
  min-height: 300px;
  max-width: 750px;
  margin: 0 auto;
}

text { font-size: 1.2em; }
line { display: none;    }

[text-anchor="end"] .domain    { d: path("M 0 0.5 H 0.5 V 250.5 H 0"); }
[text-anchor="middle"] .domain { d: path("M 0.5 6 V 0.5 H 531.5 V 0"); }
</style>

<div id="graph-wrapper">
    <svg></svg>
</div>

D3 Bar Chart Script

After retrieving the element with the select method, we can draw shapes with append(). Notice .append used multiple times in this d3 bar chart. Append then modifies the element by chaining methods. Similar to archaic jQuery. What’s more, is we manipulate the DOM. Here however, animation occurs between values.

Harnessing D3’s real power however comes in when we introduce data. Done so either by an array or an external file. D3 will draw a shape for every point in the data set.

Similar to RxJSs’ observables’ three methods of next, error, and complete… D3 has enter, update, and exit. Enter occurs on shape initialization. The update method occurs when there’s changes to the data set, giving devs the ability to react on changes. To no surprise, D3 also provides methods to listen for events, such as mouseover on tool tips for instance (view full code at Stackblitz).

var parentDiv = document.getElementById('graph-wrapper'),
    svg = d3.select('svg'),
    svgWidth = parentDiv.offsetWidth,
    svgHeight = parentDiv.offsetHeight,
    margin = { top: 20, right: 30, bottom: 30, left: 60 },
    innerWidth = svgWidth - margin.left - margin.right,
    innerHeight = svgHeight - margin.top - margin.bottom,
    colors = ['#D65076', '#45B8AC', '#EFC050', '#5B5EA6', '#9B2335'],
    aspect = svgWidth / svgHeight;

function renderData(data) {
  var xScale = d3
      .scaleLinear()
      .domain([0, d3.max(data, (d) => d.amount)])
      .range([0, innerWidth]),
    yScale = d3
      .scaleBand()
      .domain(data.map((d) => d.item))
      .range([0, innerHeight])
      .padding(0.04);

  var g = svg
    .append('g');

  var formattedVal = (number) => d3.format('.3s')(number).replace('G', 'B');

  var yAxis = d3.axisLeft(yScale);
  var xAxis = d3.axisBottom(xScale).tickFormat(formattedVal);
  yAxis(g.append('g'));
  xAxis(g.append('g').attr('transform', 'translate(0, ' + innerHeight + ')'));

  g.selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
    .attr('transform', 'translate(4, 0)')
    .attr('y', (d) => yScale(d.item))
    .attr('fill', (d, i) => {
      return colors[i];
    })
    .attr('width', (d) => xScale(d.amount))
    .attr('height', yScale.bandwidth()); // computed width of a single bar
}

window.addEventListener('resize', resizeGraph);

I think I seriously found D3 more confusing (initially) than Angular. I was new to data visualization libraries and techniques. Where we work and what we build no doubt defines us as developers. Developing data driven visualizations has no doubt made me a far better UI developer.

If you’re looking for other JavaScript projects, this has some neat features.

For a good project involving pulling in data, this sidebar is a solid bet. Or this date picker for quick, yet powerful TypeScript.

After the uphill battle, I found the lib to be powerful, malleable, and quite unique. See a working version here. Regardless of where you’re at in your career, take some time and build a D3 bar chart.

Be the first to comment

Leave a Reply

Your email address will not be published.


*