How to make a chart(line chart + area chart)- 6 mins
The components of this chart include:
- a area chart
- a line chart
- an indicator group which contains a horizontal line, a vertical line, and a tooltip
The data is public here, the CSB file contains stock price & volumes of Baidu in the last 12 months.
Let’s say what we want to present in this chart is the close value trend in the past year.
Since the chart is originated from the plain area chart, let’s start by implement an area chart first.
The margin convention wrote by Mike is very clear, admittedly this is not the only way to handle margins, but most of the time, following this convention can save you lots of troubles when the lines or areas are rendered.
Scales and Axes
Apparently we need to make an x axe presenting time(or date in this case). If you’ve only seen a few d3.js tutorials, the chances are high that you don’t know there is a dedicated api for time scale(
The date in our raw data is in the format of
2014-09-01, let’s create a range for x scale:
However, we can only add the flexible domain to xScale after the data is loaded.
Handle Raw Data
There are six columns in the origin data file, but for this chart, assume we only need to see the close value change over time. Are you thinking about open up the CSV file and edit it in Excel? No need, there is an accessor function in
d3.csv which is very convenient for us to tweak origin data. In this case, we only need two columns: date and close value for that date.
After processing with accessor function, the data is ready to use.
As seen in the accessor function, there is a dateParser function to process the date string, so what is this function for?
var dateParser = d3.time.format("%Y/%m/%d").parse;
You must remember that we use
d3.time.scale for xScale in the previous step. For time scale, in fact, domain values are coerced to dates rather than numbers. Thus, we need to format the string in the csv.
One interesting thing about time format is that what
var format = d3.time.format("%Y-%m-%d") returns is both an object and a function:
we will use both of them in this chart.
After setting scales and axis, the most import step to draw the area chart is to create an area generator.
The last step for rendering the area chart is to use the area generator. One thing to note is that, in this chart, there is only one area (and one line later), so we actually don’t need use
d3.data(). Let’s use datum instead.
The date of xAxis may not be what you want, luckily it can be easily converted by time format:
As mentioned in the official document, area chart is can be used with line chart if we want to ‘highlight’ the edge of the area chart. The steps are similar with one difference, instead of using area generator, we need a line generator looks like this:
What we want to achieve by using indicators is that when users hovering on the data points, they will be able to see the tooltip with relevant text and also one horizontal line and one vertical line to indicate the value on x and y axe.
Note that we use
selection.datum for line and area, if you look at the console, you’ll see that there is two path element, one for line, the other for area. But if we want to achieve the interaction mentioned above, we need to sort of generate a scatterplot, which means this time, we need
As for the indicator lines, I attempted to use
rect initially, but it was not that applicable in this case since the very nature of rect is to grow from the top-left corner. So I turned into
Personally I think it’s better to group those annotation together in one place, that’s why I created an
indicatorGroup to save the tooltip, the lines. Another benefit of this is that when you add new line elements, you can nest selections within the indicator group. For example:
The selection is within the indicator group so that it won’t affect other line elements on the chart.
As usual, we use class to control the tooltip, and we can use time format here again for any time format output you prefer.
Although the position of the tooltip is not very flexible yet.