Data-Driven Documents-D3

Baskarasothy Pratheeparaj
4 min readOct 16, 2020

D3 stands for Data-Driven Documents. It is an open-source JavaScript library developed by Mike Bostock to create custom interactive data visualizations in the web browser using SVG, HTML and CSS.

It is similar to Protovis in concept but while Protovis is used for static visualizations, D3 focuses more on interactions, transitions and transformations.

Why would You create charts with D3 in the first place? Why not just display an image?

Charts are based on information coming from third-party resources which requires dynamic visualization during render time. Also, SVG is a very powerful tool which fits well to this application case.

The benefits of SVG

SVG stands for Scalable Vector Graphics which is technically an XML based markup language.

It is commonly used to draw vector graphics, specify lines and shapes or modify existing images. You can find the list of available elements here.

Pros:

  • Supported in all major browsers;
  • It has DOM interface, requires no third-party lib;
  • Scalable, it can maintain high resolution;
  • Reduced size compared to other image formats.

Cons:

  • It can only display two-dimensional images;
  • Long learning curve;
  • Render may take long with compute-intensive operations.

Despite its downsides, SVG is a great tool to display icons, logos, illustrations or in this case, charts

Getting Started with D3

If you use npm, npm install d3. Otherwise, download the latest release. The released bundle supports anonymous AMD, CommonJS, and vanilla environments. You can load directly from d3js.org, CDNJS, or unpkg.

I picked bar chart to get started because it represents a low complexity visual element while it teaches the basic application of D3.js itself. This should not deceive You, D3 provides a great set of tools to visualize data.

Drawing Bars in D3.js

Think about what kind of input we need to draw the bars. They each represent a value which is illustrated with simple shapes, specifically rectangles. In the next code snippet, I append them to the created group element.

I want to create a chart with 1000 pixels width and 600 pixels height.

const margin = 60;    
const width = 1000 - 2 * margin;
const height = 600 - 2 * margin;
const svg = d3.select('svg');
const chart = svg.append('g')
.attr('transform', `translate(${margin}, ${margin})`);

I’ve define a margin value which gives a little extra padding to the chart. Padding can be applied with a <g> element translated by the desired value. From now on, I draw on this group to keep a healthy distance from any other contents of the page.

const chart = svg.append('g')     
.attr('transform', `translate(${margin}, ${margin})`);

Adding attributes to an element is as easy as calling the attr method. The method’s first parameter takes an attribute I want to apply to the selected DOM element. The second parameter is the value or a callback function that returns the value of it. The code above simply moves the start of the chart to the (60;60) position of the SVG.

Scaling, Axes

const yScale = d3.scaleLinear()     
.range([height, 0])
.domain([0, 100]);

Linear scale is the most commonly known scaling type. It converts a continuous input domain into a continuous output range. Notice the range and domain method. The first one takes the length that should be divided between the limits of the domain values.

Now, continue with the x-axis.

const xScale = d3.scaleBand()     
.range([0, width])
.domain(sample.map((s) => s.language))
.padding(0.2)
chart.append('g')
.attr('transform', `translate(0, ${height})`) .call(d3.axisBottom(xScale));

Drawing Bars in D3

Think about what kind of input we need to draw the bars. They each represent a value which is illustrated with simple shapes, specifically rectangles. In the next code snippet, I append them to the created group element.

chart.selectAll()     
.data(goals)
.enter()
.append('rect')
.attr('x', (s) => xScale(s.language))
.attr('y', (s) => yScale(s.value))
.attr('height', (s) => height - yScale(s.value))
.attr('width', xScale.bandwidth())

First, I selectAll elements on the chart which returns with an empty result set. Then, data function tells how many elements the DOM should be updated with based on the array length. enter identifies elements that are missing if the data input is longer than the selection. This returns a new selection representing the elements that need to be added. Usually, this is followed by an append which adds elements to the DOM.

Now, this only adds rectangles on top of each other which have no height or width. These two attributes have to be calculated and that’s where the scaling functions come handy again.

See, I add the coordinates of the rectangles with the attr call. The second parameter can be a callback which takes 3 parameters: the actual member of the input data, index of it and the whole input.

.attr(’x’, (actual, index, array) =>     
xScale(actual.value))

I define the width of the rectangles with the scaling function as well. scaleBand has a bandwidth function which returns the computed width for one element based on the set padding.

Finally

we got a bar chart that representing top 10 most loved programming languages based on Stack Overflow’s 2018 https://insights.stackoverflow.com/survey/2018/#technology-most-loved-dreaded-and-wanted-languages

Nice job, but not so fancy, right?

we can Add Style and more Information for this bar chart. we will Try on another blog about Fancy Bar chart

I hope that you will get some idea from this blog however, Keep learning keep coding :D

--

--