Line, Area, and Scatter Charts

Exclusive offer: get 50% off this eBook here
Learning Highcharts

Learning Highcharts — Save 50%

Create rich, intuitive, and interactive JavaScript data visualization for your web and enterprise development needs using this powerful charting library — Highcharts

$26.99    $13.50
by Joe Kuan | April 2013 | Open Source

In this article by Joe Kuan, the author of the book Learning Highcharts, we will cover the following topics:

  • Introducing line charts

  • Sketching an area chart

  • Mixing line and area series

  • Combining scatter and area series

(For more resources related to this topic, see here.)

Introducing line charts

First let's start with a single series line chart. We will use one of the many data provided by The World Bank organization at www.worldbank.org. The following is the code snippet to create a simple line chart which shows the percentage of population ages, 65 and above, in Japan for the past three decades:

var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
title: {
text: 'Population ages 65 and over (% of total)',
},
credits: {
position: {
align: 'left',
x: 20
},
text: 'Data from The World Bank'
},
yAxis: {
title: {
text: 'Percentage %'
}
},
xAxis: {
categories: ['1980', '1981',
'1982', ... ],
labels: {
step: 5
}
},
series: [{
name: 'Japan - 65 and over',
data: [ 9, 9, 9, 10, 10, 10, 10 ... ]
}]
});

The following is the display of the simple chart:

Instead of specifying the year number manually as strings in categories, we can use the pointStart option in the series config to initiate the x-axis value for the first point. So we have an empty xAxis config and series config, as follows:

xAxis: {
},
series: [{
pointStart: 1980,
name: 'Japan - 65 and over',
data: [ 9, 9, 9, 10, 10, 10, 10 ... ]
}]

Although this simplifies the example, the x-axis labels are automatically formatted by Highcharts utility method, numberFormat, which adds a comma after every three digits. The following is the outcome on the x axis:

To resolve the x-axis label, we overwrite the label's formatter option by simply returning the value to bypass the numberFormat method being called. Also we need to set the allowDecimals option to false. The reason for that is when the chart is resized to elongate the x axis, decimal values are shown. The following is the final change to use pointStart for the year values:

xAxis: {
labels:{
formatter: function() {
// 'this' keyword is the label object
return this.value;
}
},
allowDecimals: false
},
series: [{
pointStart: 1980,
name: 'Japan - 65 and over',
data: [ 9, 9, 9, 10, 10, 10, 10 ... ]
}]

Extending to multiple series line charts

We can include several more line series and set the Japan series by increasing the line width to be 6 pixels wide, as follows:

series: [{
lineWidth: 6,
name: 'Japan',
data: [ 9, 9, 9, 10, 10, 10, 10 ... ]
}, {
Name: 'Singapore',
data: [ 5, 5, 5, 5, ... ]
}, {
...
}]

The line series for Japanese population becomes the focus in the chart, as shown in the following screenshot:

Let's move on to a more complicated line graph. For the sake of demonstrating inverted line graphs, we use the chart.inverted option to flip the y and x axes to opposite orientations. Then we change the line colors of the axes to match the same series colors. We also disable data point markers for all the series and finally align the second series to the second entry in the y-axis array, as follows:

chart: {
renderTo: 'container',
inverted: true,
},
yAxis: [{
title: {
text: 'Percentage %'
},
lineWidth: 2,
lineColor: '#4572A7'
}, {
title: {
text: 'Age'
},
opposite: true,
lineWidth: 2,
lineColor: '#AA4643'
}],
plotOptions: {
series: {
marker: {
enabled: false
}
}
},
series: [{
name: 'Japan - 65 and over',
type: 'spline',
data: [ 9, 9, 9, ... ]
}, {
name: 'Japan - Life Expectancy',
yAxis: 1,
data: [ 76, 76, 77, ... ]
}]

The following is the inverted graph with double y axes:

The data representation of the chart may look slightly odd as the usual time labels are swapped to the y axis and the data trend is awkward to comprehend. The inverted option is normally used for showing data in a noncontinuous form and in bar format. If we interpret the data from the graph, 12 percent of the population is 65 and over, and the life expectancy is 79 in 1990.

By setting plotOptions.series.marker.enabled to false it switches off all the data point markers. If we want to display a point marker for a particular series, we can either switch off the marker globally and then set the marker on an individual series, or the other way round.

plotOptions: {
series: {
marker: {
enabled: false
}
}
},
series: [{
marker: {
enabled: true
},
name: 'Japan - 65 and over',
type: 'spline',
data: [ 9, 9, 9, ... ]
}, {

The following graph demonstrates that only the 65 and over series has point markers:

Sketching an area chart

In this section, we are going to use our very first example and turn it into a more stylish graph (based on the design of wind energy poster by Kristin Clute), which is an area spline chart. An area spline chart is generated using the combined properties of area and spline charts. The main data line is plotted as a spline curve and the region underneath the line is filled in a similar color with a gradient and an opaque style.

Firstly, we want to make the graph easier for viewers to look up the values for the current trend, so we move the y axis next to the latest year, that is, to the opposite side of the chart:

yAxis: { ....
opposite:true
}

The next thing is to remove the interval lines and have a thin axis line along the y axis:

yAxis: { ....
gridLineWidth: 0,
lineWidth: 1,
}

Then we simplify the y-axis title with a percentage sign and align it to the top of the axis:

yAxis: { ....
title: {
text: '(%)',
rotation: 0,
x: 10,
y: 5,
align: 'high'
},
}

As for the x axis, we thicken the axis line with a red color and remove the interval ticks:

xAxis: { ....
lineColor: '#CC2929',
lineWidth: 4,
tickWidth: 0,
offset: 2
}

For the chart title, we move the title to the right of the chart, increase the margin between the chart and the title, and then adopt a different font for the title:

title: {
text: 'Population ages 65 and over (% of total) -
Japan ',
margin: 40,
align: 'right',
style: {
fontFamily: 'palatino'
}
}

After that we are going to modify the whole series presentation, we first set the chart.type property from 'line' to 'areaspline'. Notice that setting the properties inside this series object will overwrite the same properties defined in plotOptions.areaspline and so on in plotOptions.series.

Since so far there is only one series in the graph, there is no need to display the legend box. We can disable it with the showInLegend property. We then smarten the area part with gradient color and the spline with a darker color:

series: [{
showInLegend: false,
lineColor: '#145252',
fillColor: {
linearGradient: {
x1: 0, y1: 0,
x2: 0, y2: 1
},
stops:[ [ 0.0, '#248F8F' ] ,
[ 0.7, '#70DBDB' ],
[ 1.0, '#EBFAFA' ] ]
},
data: [ ... ]
}]

After that, we introduce a couple of data labels along the line to indicate that the ranking of old age population has increased over time. We use the values in the series data array corresponding to the year 1995 and 2010, and then convert the numerical value entries into data point objects. Since we only want to show point markers for these two years, we turn off markers globally in plotOptions.series. marker.enabled and set the marker on, individually inside the point objects accompanied with style settings:

plotOptions: {
series: {
marker: {
enabled: false
}
}
},
series: [{ ...,
data:[ 9, 9, 9, ...,
{ marker: {
radius: 2,
lineColor: '#CC2929',
lineWidth: 2,
fillColor: '#CC2929',
enabled: true
},
y: 14
}, 15, 15, 16, ... ]
}]

We then set a bounding box around the data labels with round corners (borderRadius) in the same border color (borderColor) as the x axis. The data label positions are then finely adjusted with the x and y options. Finally, we change the default implementation of the data label formatter. Instead of returning the point value, we print the country ranking.

series: [{ ...,
data:[ 9, 9, 9, ...,
{ marker: {
...
},
dataLabels: {
enabled: true,
borderRadius: 3,
borderColor: '#CC2929',
borderWidth: 1,
y: -23,
formatter: function() {
return "Rank: 15th";
}
},
y: 14
}, 15, 15, 16, ... ]
}]

The final touch is to apply a gray background to the chart and add extra space into spacingBottom. The extra space for spacingBottom is to avoid the credit label and x-axis label getting too close together, because we have disabled the legend box.

chart: {
renderTo: 'container',
spacingBottom: 30,
backgroundColor: '#EAEAEA'
},

When all these configurations are put together, it produces the exact chart, as shown in the screenshot at the start of this section.

Mixing line and area series

In this section we are going to explore different plots including line and area series together, as follows:

  • Projection chart, where a single trend line is joined with two series in different line styles

  • Plotting an area spline chart with another step line series

  • Exploring a stacked area spline chart, where two area spline series are stacked on top of each other

Simulating a projection chart

The projection chart has spline area with the section of real data and continues in a dashed line with projection data. To do that we separate the data into two series, one for real data and the other for projection data. The following is the series configuration code for the future data up to 2024. This data is based on the National Institute of Population and Social Security Research report (http://www.ipss.go.jp/pp-newest/e/ppfj02/ppfj02.pdf).

series: [{
name: 'project data',
type: 'spline',
showInLegend: false,
lineColor: '#145252',
dashStyle: 'Dash',
data: [ [ 2010, 23 ], [ 2011, 22.8 ],
... [ 2024, 28.5 ] ]
}]

The future series is configured as a spline in a dashed line style and the legend box is disabled, because we want to show both series as being from the same series. Then we set the future (second) series color the same as the first series. The final part is to construct the series data. As we specify the x-axis time data with the pointStart property, we need to align the projection data after 2010. There are two approaches that we can use to specify the time data in a continuous form, as follows:

  • Insert null values into the second series data array for padding to align with the real data series

  • Specify the second series data in tuples, which is an array with both time and projection data

Next we are going to use the second approach because the series presentation is simpler. The following is the screenshot only for the future data series:

The real data series is exactly the same as the graph in the screenshot at the start of the Sketching an area chart section, except without the point markers and data label decorations. The next step is to join both series together, as follows:

series: [{
name: 'real data',
type: 'areaspline',
....
}, {
name: 'project data',
type: 'spline',
....
}]

Since there is no overlap between both series data, they produce a smooth projection graph:

Contrasting spline with step line

In this section we are going to plot an area spline series with another line series but in a step presentation. The step line transverses vertically and horizontally only according to the changes in series data. It is generally used for presenting discrete data, that is, data without continuous/gradual movement.

For the purpose of showing a step line, we will continue from the first area spline example. First of all, we need to enable the legend by removing the disabled showInLegend setting and also remove dataLabels in the series data.

Next is to include a new series, Ages 0 to 14, in the chart with a default line type. Then we will change the line style slightly differently into steps. The following is the configuration for both series:

series: [{
name: 'Ages 65 and over',
type: 'areaspline',
lineColor: '#145252',
pointStart: 1980,
fillColor: {
....
},
data: [ 9, 9, 9, 10, ...., 23 ]
}, {
name: 'Ages 0 to 14',
// default type is line series
step: true,
pointStart: 1980,
data: [ 24, 23, 23, 23, 22, 22, 21,
20, 20, 19, 18, 18, 17, 17, 16, 16, 16,
15, 15, 15, 15, 14, 14, 14, 14, 14, 14,
14, 14, 13, 13 ]
}]

The following screenshot shows the second series in the stepped line style:

Learning Highcharts Create rich, intuitive, and interactive JavaScript data visualization for your web and enterprise development needs using this powerful charting library — Highcharts
Published: December 2012
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Extending to a stacked area chart

In this section we are going to turn both series into area splines and stack them on top of each other to create a stacked area chart. As the data series are stacked together, we can observe the series quantity roughly in individual, proportional, and total formats.

Let's change the second series into another 'areaspline' type:

name: 'Ages 0 to 14',
type: 'areaspline',
pointStart: 1980,
data: [ 24, 23, 23, ... ]

Set the stacking option to 'normal' as a default setting for areaspline, as follows:

plotOptions: {
areaspline: {
stacking: 'normal'
}
}

This sets both area graphs stacked on top of each other. By doing so we can observe from the data that both age groups of population roughly compensate each other to make up a total of around 33 percent of the total population and the Ages 65 and over group is increasingly outpaced in the later stage:

Suppose we have three area spline series and we only want to stack two of them (although it is clearer to do that in a columns chart than in an area spline chart). We can set the stacking option in plotOptions.series to 'normal', and manually turn off stacking in the third series configuration. The following is the series configuration with another series:

plotOptions: {
series: {
marker: {
enabled: false
},
stacking: 'normal'
}
},
series: [{
name: 'Ages 65 and over',
....
}, {
name: 'Ages 0 to 14',
....
}, {
name: 'Ages 15 to 64',
type: 'areaspline',
pointStart: 1980,
stacking: null,
data: [ 67, 67, 68, 68, .... ]
}]

This creates an area spline graph with the third series, Ages 15 to 64, covering the other two stacked series, as shown in the following screenshot:

Plotting charts with missing data

If a series has missing data, then Highcharts' default action is to display the series as a broken line. There is an option, connectNulls, which allows the series line to continue even if there is missing data. The default value for this option is false. Let's examine the default behavior by setting two spline series with null data points. Also, we enable the point markers, so that we can clearly view the missing data points:

series: [{
name: 'Ages 65 and over',
connectNulls: true,
....,
// Missing data from 2004 - 2009
data: [ 9, 9, 9, ...., 23 ]
}, {
name: 'Ages 0 to 14',
....,
// Missing data from 1989 - 1994
data: [ 24, 23, 23, ...., 13 ]
}]

The following is a chart with a spline series presenting missing points in different styles:

As we can see the Ages 0 to 14 series has a clear broken line, whereas Ages 65 and over is configured with setting connectNulls to true, which joins the missing points with a spline curve. If the point marker is not enabled, we won't be able to notice the difference.

However, we should use this option with caution and should especially never enable it with the stacking option. Suppose we have a stacked area chart with both series and there is missing data only in the Ages 0 to 14 series, which is the bottom series. The default action for the missing data will make the graph look like the following screenshot:

Although the bottom series does show the broken part, the stack graph overall still remains correct. The same area of the top series drops back to single series values and the overall percentage is still intact.

The problem arises when we set the connectNulls option to true and do not realize that there is missing data in the series. This results in an inconsistent graph, as follows:

The bottom series covers a hole left from the top series, which contradicts the stack graph's overall percentage.

Combining scatter and area series

Highcharts also supports scatter charts that enable us to plot the data trend from a large set of data samples. In here we are going to use scatter series differently which makes our chart a bit like a poster chart.

First, we are going to use a subset of the'Ages 0 to 14' data and set the series to the scatter type:

name: 'Ages 0 to 14',
type: 'scatter',
data: [ [ 1982, 23 ], [ 1989, 19 ],
[ 2007, 14 ], [ 2004, 14 ],
[ 1997, 15 ], [ 2002, 14 ],
[ 2009, 13 ], [ 2010, 13 ] ]

Then we will enable the data labels for the scatter series and make sure the marker shape is always 'circle', as follows:

plotOptions: {
scatter: {
marker: {
symbol: 'circle'
},
dataLabels: {
enabled: true
}
}
}

The preceding code snippet gives us the following graph:

Highcharts provides a list of marker symbols as well as allowing users to supply their own marker icons. The list of supported symbols contains circle, square, diamond, triangle , and triangle-down.

Polishing a chart with an artistic style

The next step is to format each scatter point into a bubble style with the radius property and manually set the data label font size proportional to the percentage value. Then use the verticalAlign property to adjust the labels to center inside the enlarged scatter points. The various sizes of the scatter points require us to present each data point with different attributes. Hence, we need to change the series data definition into an array of point object configurations, such as:

plotOptions: {
scatter: {
marker: {
symbol: 'circle'
},
dataLabels: {
enabled: true,
verticalAlign: 'middle'
}
}
},
data: [ {
dataLabels: {
style: {
fontSize: '25px'
}
},
marker: { radius: 31 },
y: 23,
x: 1982
}, {
dataLabels: {
style: {
fontSize: '22px'
}
},
marker: { radius: 23 },
y: 19,
x: 1989
}, .....

The following screenshot shows a graph with a sequence of data points from a large marker size and font, gradually becoming smaller according to their percentage values:

Now we have two issues with the preceding graph. Firstly, the scatter series color (default second series color) clashes with the gray text label inside the markers making it hard to read.

To resolve the first issue we will change the scatter series to a lighter color with the following gradient setting:

color: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [ [ 0, '#FF944D' ],
[ 1, '#FFC299' ] ]
},

Then we give the scatter points a darker outline in plotOptions, as follows:

plotOptions: {
scatter: {
marker: {
symbol: 'circle',
lineColor: '#E65C00',
lineWidth: 1
},

Secondly, the data points are blocked by the end of the axes range. The issue can be resolved by introducing extra padding spaces into both axes:

yAxis: {
.....,
maxPadding: 0.09
},
xAxis: {
.....,
maxPadding: 0.02
}

The following is the new outlook of the graph:

For the next part we will put up a logo and some decorative texts. There are two ways to import an image into a chart—the plotBackgroundImage option or the renderer.image API call. The plotBackgroundImage option brings the whole image into the chart background which is not what we intend to do. The renderer. image method offers more control on the location and the size of the image. The following is the call after the chart is created:

var chart = new Highcharts.Chart({
...
});
chart.renderer.image('logo.png', 240, 10, 187, 92).add();

logo.png is the URL path for the logo image file; the next two parameters are the x and y positions (starting from 0, where 0 is the upper-left corner) of the chart where the image will be displayed; the last two parameters are the width and height of the image file. The image call basically returns an element object and the subsequent .add call puts the returned image object into the renderer.

As for the decorative text, it is a red circle with white bold text in a different size. They are all created from the renderer. In the following code snippet the first renderer call is to create a red circle with x and y locations, and radius size. Then immediately the SVG attributes with the attr method are set, which configures the transparency and outline in a darker color. The next three renderer calls are to create text inside the red circle and the it is set up by using the css method for font size, style, and color.

// Red circle at the back
chart.renderer.circle(220, 65, 45).attr({
fill: '#FF7575',
'fill-opacity': 0.6,
stroke: '#B24747',
'stroke-width': 1
}).add();
// Large percentage text with special font
chart.renderer.text('37.5%', 182, 63).css({
fontWeight: 'bold',
color: #FFFFFF',
fontSize: '30px',
fontFamily: 'palatino'
}).add();
// Align subject in the circle
chart.renderer.text('65 and over', 184, 82).css({
'fontWeight': 'bold',
}).add();
chart.renderer.text('by 2050', 193, 96).css({
'fontWeight': 'bold',
}).add();

Finally, we move the legend box to the top of the chart. In order to locate the legend inside the plot area, we need to set the floating property to true which forces the legend into a fixed layout mode. Then we remove the default border line and set the legend items' list into a vertical direction:

legend: {
floating: true,
verticalAlign: 'top',
align: 'center',
x: 130,
y: 40,
borderWidth: 0,
layout: 'vertical',
},

The following is our final graph with the decorations:

Summary

This article demonstrated from plotting a simple line, area, and scatter charts to a poster-like chart.

Resources for Article :


Further resources on this subject:


Learning Highcharts Create rich, intuitive, and interactive JavaScript data visualization for your web and enterprise development needs using this powerful charting library — Highcharts
Published: December 2012
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Joe Kuan

Joe Kuan was born in Hong Kong and continued his education in the UK from secondary school to university. He studied Computer Science at University of Southampton for B.Sc. and Ph.D. After his education, he worked with different technologies and industries in the UK for more than a decade. Currently, he is working for iTrinegy – a company specializing in network emulation and performance monitoring. Part of his role is to develop frontend and present complex network data into stylish and interactive charts. He has adopted Highcharts with iTrinegy for nearly three years. Since then, he has been contributing blogs and software on Highcharts and Highstocks.

Apart from his busy family schedule and active outdoor lifestyle, he occasionally writes articles for his own blog site http://joekuan.wordpress.com and puts some demonstrations up at http://joekuan.org. You can contact him at learning.highcharts@gmail.com.

Books From Packt


FusionCharts Beginner’s Guide: The Official Guide for FusionCharts Suite
FusionCharts Beginner’s Guide: The Official Guide for FusionCharts Suite

JasperReports 3.6 Development Cookbook
JasperReports 3.6 Development Cookbook

gnuplot Cookbook
gnuplot Cookbook

Oracle SOA Suite 11g Administrator's Handbook
HTML5 Graphing and Data Visualization Cookbook

ActionScript Graphing Cookbook
ActionScript Graphing Cookbook

BIRT 2.6 Data Analysis and Reporting
BIRT 2.6 Data Analysis and Reporting

Practical Data Analysis and Reporting with BIRT
Practical Data Analysis and Reporting with BIRT

iReport 3.7
iReport 3.7


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software