# Creating Simple Line and Bar Charts Using D3.js

In a previous article, we learned how to implement bubble charts using D3.js, a JavaScript library for creating data-driven documents. D3.js helps to visualize data using HTML, SVG, and CSS. In this article, we’ll see how to implement line and bar charts using D3.js. Before moving on, you should download D3.js and be familiar with the material in my previous article.

## Creating Line Charts

First, we’ll need some data to plot. We’re going to use the following data.

``````var lineData = [{
x: 1,
y: 5
}, {
x: 20,
y: 20
}, {
x: 40,
y: 10
}, {
x: 60,
y: 40
}, {
x: 80,
y: 5
}, {
x: 100,
y: 60
}];``````

We’re also going to need a `<svg>` element to plot our graph on.

``<svg id="visualisation" width="1000" height="500"></svg>``
Watch Visualize Data with D3.js
Illustrate Your Data with JavaScript

Next, we need to create our x and y axes, and for that we’ll need to declare a domain and range. The domain defines the minimum and maximum values displayed on the graph, while the range is the amount of the SVG we’ll be covering. Both of the axes need to scale as per the data in `lineData`, meaning that we must set the domain and range accordingly. The code for drawing the axes is shown below.

``````var vis = d3.select('#visualisation'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) {
return d.x;
}), d3.max(lineData, function(d) {
return d.x;
})]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) {
return d.y;
}), d3.max(lineData, function(d) {
return d.y;
})]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient('left')
.tickSubdivide(true);

vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);

vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);``````

In this code, we have defined the `WIDTH`, `HEIGHT`, and `MARGINS` for our graph. The `xRange` and `yRange` variables represent the domains for the respective axes. We set the range for our axes as per the left and right margins.

Next, since the domain is the data we will show on the graph, we need to get the min and max values from `lineData`. This is done using the `d3.max()` and `d3.min()` methods.

Next, we created our axes as per the `xRange` and `yRange` variables. For both axes, we have defined the scale as `xRange` and `yRange` for the X and Y axes, respectively. And then we simply appended both the axis to the SVG and applied the transform. Now, if we have a look at the Y axis it needs to be oriented to the left. Hence, we applied a left orientation to the `yAxis`. We have transformed both the axes, keeping the defined margins in view so that the axes don’t touch the SVG margins.

Here is a demo of the above code showing both axes.

Next, we need to apply the `xRange` and the `yRange` to the coordinates to transform them into the plotting space and to draw a line across the plotting space. We’ll be using `d3.svg.line()` to draw our line graph. For this, we need to create a line generator function which returns the x and y coordinates from our data to plot the line. This is how we define the line generator function:

``````var lineFunc = d3.svg.line()
.x(function(d) {
return xRange(d.x);
})
.y(function(d) {
return yRange(d.y);
})
.interpolate('linear');``````

The `interpolate('linear')` call tells D3 to draw straight lines.

Next, we need to set the `d` attribute of the SVG path to the coordinates returned from the line function. This is accomplished using the following code.

``````vis.append('svg:path')
.attr('d', lineFunc(lineData))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');``````

We have set the line color using `stroke`. The line’s width is defined using `stroke-width`. We have set `fill` to `none`, as not to fill the graph boundaries. Here is a demo of the line graph with `linear` interpolation in action, and here is the same graph demo with `basis` interpolation.

## Creating Bar Charts

Next, we’ll look at creating bar charts. Since, we already created our axes, we won’t need to reinvent the wheel. However, we will modifiy the existing code a bit. First, the sample data and code for creating our chart’s axes:

``````function InitChart() {

var barData = [{
'x': 1,
'y': 5
}, {
'x': 20,
'y': 20
}, {
'x': 40,
'y': 10
}, {
'x': 60,
'y': 40
}, {
'x': 80,
'y': 5
}, {
'x': 100,
'y': 60
}];

var vis = d3.select('#visualisation'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(barData, function(d) {
return d.x;
}),
d3.max(barData, function (d) {
return d.x;
})
]),

yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(barData, function(d) {
return d.y;
}),
d3.max(barData, function (d) {
return d.y;
})
]),

xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),

yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient("left")
.tickSubdivide(true);

vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);

vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
}

InitChart();``````

Here is a demo of the previous code. If you have a look at the Y axis, the scale starts at five. This minimum comes from our sample data, where 5 is the min Y value. Therefore, we need to scale the Y axis from 0. For that, we need to modify the domain of the `yRange` in the `InitChart()` function as shown below:

``````yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0,
d3.max(barData, function(d) {
return d.y;
})]);``````

In the case of bar charts, we’ll be using `ordinal` scales instead of the `linear` scales. Ordinal scales help to maintain a discrete domain. For a more detailed info refer to the official documentation on ordinal scales.

We’ll also be using `rangeRoundBands` to divide the width across the chart bars. We’ll modify the `xRange` using `ordinal` scale and `rangeRoundBands` as shown below. Notice that we have also set the spacing between the bars to 0.1.

``````xRange = d3.scale.ordinal().rangeRoundBands([MARGINS.left, WIDTH - MARGINS.right], 0.1).domain(barData.map(function(d) {
return d.x;
}));``````

Next, we need to create rectangular bars for the chart data. We’ll be binding our sample data to the rectangles, using the x and y coordinates to set the `height` and `width` of the rectangular bars. Here is how the code looks:

``````vis.selectAll('rect')
.data(barData)
.enter()
.append('rect')
.attr('x', function(d) { // sets the x position of the bar
return xRange(d.x);
})
.attr('y', function(d) { // sets the y position of the bar
return yRange(d.y);
})
.attr('width', xRange.rangeBand()) // sets the width of bar
.attr('height', function(d) {      // sets the height of bar
return ((HEIGHT - MARGINS.bottom) - yRange(d.y));
})
.attr('fill', 'grey');   // fills the bar with grey color``````

Here is a demo of our bar chart in action.

## Adding Events

In order to improve interactivity, we can also attach events to the bars. We can attach an event to highlight the bar on `mouseover`. Here is how it can be accomplished:

``````vis.selectAll('rect')
.data(barData)
.enter()
.append('rect')
.attr('x', function(d) {
return xRange(d.x);
})
.attr('y', function(d) {
return yRange(d.y);
})
.attr('width', xRange.rangeBand())
.attr('height', function(d) {
return ((HEIGHT - MARGINS.bottom) - yRange(d.y));
})
.attr('fill', 'grey')
.on('mouseover', function(d) {
d3.select(this)
.attr('fill', 'blue');
});``````

In this code, the `on('mouseover')` adds an event handler that is invoked on mouse over, which makes the hovered bars blue. Here is a demo that illustrates this effect.

You might notice that the bars don’t turn grey again on `mouseout`. Let’s attach another event to revert it back to its previous color on mouse out. The updated code is shown below:

``````vis.selectAll('rect')
.data(barData)
.enter()
.append('rect')
.attr('x', function(d) {
return xRange(d.x);
})
.attr('y', function(d) {
return yRange(d.y);
})
.attr('width', xRange.rangeBand())
.attr('height', function(d) {
return ((HEIGHT - MARGINS.bottom) - yRange(d.y));
})
.attr('fill', 'grey')
.on('mouseover', function(d) {
d3.select(this)
.attr('fill', 'blue');
})
.on('mouseout', function(d) {
d3.select(this)
.attr('fill', 'grey');
});``````

And, here is a demo of the above code in action.

## Conclusion

D3.js is an awesome JavaScript libray for data visualization. In this tutorial, we focused on creating fairly simple bar and line charts. If you’re interested in experimenting more, try adding additional visualization techniques from the D3 library to the charts in this article.