Official website for Web Designer - defining the internet through beautiful design
FOLLOW US ON:
Author: Steve Jenkins
29th July 2013

Build HTML5 charts with Chart.js

Impress yourself and your users with swish, animation-ready HTML5 charts to communicate your data and vision

Build HTML5 charts with Chart.js
Data is the backbone of the web, and in the web’s early days, documents were shared between academic institutions. But large amounts of raw data can be hard to understand; this is where data visualisation comes in. All of a sudden great swathes of tabular data that were insurmountable are transformed into easily graspable graphics. Traditionally, <table>, <svg>, and <img> were the best ways to show this data but with the widespread adoption of HTML5 in browsers <canvas> is another, rich way to show data.
In this tutorial you’ll learn how to process data and turn it into delicious-looking charts using Chart.js by Nick Downie. Its documentation contains everything you’ll need to know and get started and you’ll soon have the confidence to integrate Chart.js with your own site and style it as you wish.
We’ll create a dashboard showing the population trends of 236 species of birds, as collected by the government during 1970 and 2010 (bit.ly/ZABlQg). This data set will push Chart.js’s performance capabilities and provide us with a few ways to visualise the data.

DOWNLOAD TUTORIAL FILES

The Canvas element

Chart.js uses the HTML5 Canvas element to display it’s charts, so to start you need to make a Canvas on a new page. If you haven’t used Canvas before, fret not, there’s no need to handle the nitty gritty as the library handles that for us. Simply make a new Canvas element like any other HTML tag.

001    <main role=”main”>
002    <canvas id=”trends”></canvas>
003    </main>

Make Ajax request

Before you can visualise the data you need to get and parse the data in a way that Chart.js can use. This data is stored in an external file so you’ll need to send an Ajax request to retrieve it’s contents. You won’t be using jQuery so this is how an Ajax request looks in ‘vanilla’ JavaScript.

001 (function() {
002    var data; var url = ‘data/birds.csv’;
003    function makeRequest(url) {
004        var xhr = new XMLHttpRequest();
005     xhr.open(‘GET’, url);
006        xhr.onload = function() {
007            if (xhr.readyState === 4 && xhr.status     === 200) {/*run code*/}
008        };
009        xhr.send(null);
010    }
011 })();

Easily parse CSV

Currently the data set is locked in a CSV (Comma-Separated Values) file which is commonly generated from spreadsheet programs. Thankfully there are a few libraries that will generate usable data structures (like arrays and objects) from it. The jQuery CSV plug-in is used here as it has a toArrays method. Then you can simply write:

001    data = CSV.toArrays(xhr.responseText);

Making data usable

toArrays() gives a structure that looks like [[‘Starling’,’100’,’78.6’],[‘Magpie’,[‘100’,’98’]] so each ‘row’ is a separate array. Next up is some pretty hairy-looking code that will convert all of the values from strings to numbers (specifically floats meaning that we can use decimal points) and convert empty values in our array to a 0.

001    for (var i = 0, len = data.length; i < len;     i++) {
0012    for (var j = 0, l = data[i].length; j <     l;     j++) {
003        if (!isNaN(parseFloat(data[i][j])))
004            data[i][j] = parseFloat(data[i][j]);
005        else if (!data[i][j].length)
006                data[i][j] = 0;
007        }
008     }

Nested for loops

The line chart takes an object that lists the labels and each data set separately like: labels: [“January”,”February”], data sets: [{data: [65,59]}, {data: [28,48]}]. To replicate this with your data, create a label for each year in your data set and then populate the data sets with an individual species’ data using a couple of for loops.

001    var years = [];
002    for (var i = 0; i < 2010-1970; i++) years.    push([]);
003    for (var i = 0, len = data.length; i < len;     i++)
004        for (var j = 0, l = data[i].length; j <     l;     j++)
005        if (j === 0) labels.push(data[i][j]);
006        else years[j-1].push(data[i]    004 [j]);

Looping through inputs

Data now contains a data set that we can use to compare species. To find out which bird’s data to get, read the value of each input and set a funky colour to both the bird data and the corresponding input. Setting a colour value for the input and bird will tell the user which bird relates to which colour.

001    var birds = document.            002    getElementsByClassName(‘bird-input’);
var datasets = [];
003    for (var i = 0, len = birds.length; i <     len;     i++) {
004    var bird = findBird(birds[i].value);
005        var colour = “rgba(80,116,3,0.5)”;
006        birds[i].style.background = colour;
007     }

Push the bird

Within the for loop of Step 6, you can push the data set with your configuration options and the data set for the individual bird. You can customise the fill, stroke, and point colours individually so that your chart can look as unique as your site’s style to tie in nicely. The colours can be in hex, RGB(A), or HSL(A).

001     datasets.push({
002     fillColor: colour,
003        strokeColor: “rgb(0,0,0)”,
004        pointColor: “rgb(0,0,0)”,
005        pointStrokeColor: “#fff”,
006        data: bird
007     });

Resulting data

This is a helper function that takes the name of a bird, finds it’s index in the labels array and returns the corresponding data set. The resulting graphData variable is the compiled data that Chart.js can read to create a line, bar or radar chart. If you’re hardcoding your labels and data set then an equal amount of each is needed.

001    var findBird = function(bird) {
002    var index = labels.indexOf(bird);
003        return data[index];
004    };
005    // [...]
006    var graphData = {
007        labels: labels,
008        datasets: datasets
009    };

Setting dimensions

Set the width and height to half the viewport width and as wide as the viewport or 960px (whichever fits). Then get the canvas’s rendering context and pass this to Chart.js. Using Chart.js all you have to do is tell it ‘I want a new chart (using this canvas) and I want it to be a Line chart (using this data), please’.
001    var graph = document.            getElementById(‘trends’);
002    graph.height = window.innerHeight / 2;
003    graph.width = window.innerWidth > 960 ? 960 : window.innerWidth;
004    var ctx = graph.getContext(‘2d’),
005    chart = new Chart(ctx).Line(graphData);

Construct line chart

Refresh the page and before your eyes you should see the chart animate into life, rendering all those sexy data points. You can also pass a configuration object after the data to customise the chart, perhaps all of those animations aren’t for you? No problem. Or perhaps you don’t wish to label the Y axis. All of the options are listed at www.chartjs.org/docs/.

001    var chart = new Chart(ctx).Line(graphData, {
002        animation: false,
003        scaleShowLabels: false
004    });

Bar chart

Chart.js isn’t limited to just constructing simplistic line charts though. It also provides support for bar charts, radar charts, polar-area charts, pie charts, and doughnut charts. Using the same data as the line chart, you can swap line for bar and instantly your chart changes to a bar chart, the choice is yours.

001    var chart = new Chart(ctx).Bar(graphData);

Pie data

Next, create four pie charts, one to represent each decade, that will show the comparative success of the selected species of bird. It’s easy enough to create the pie chart with Chart.js but we have to massage the data so that Chart.js can make sense of it. This time it expects something that looks like:

001    var data = [{
002    value: 30,
003        color:”#F38630”
004    }, {
005        value : 50,
006        color : “#E0E4CC”
007    }];

Decades of data

To get the data you need, make four arrays that will contain the numbers for each bird per decade. This isn’t a very DRY (Don’t Repeat Yourself) approach but it serves the purpose. Iterate through each input, find the data for that particular bird and push each decade to it’s corresponding decade.

001    var pieData = [],
002        pieData2 = [],
003        pieData3 = [],
004        pieData4 = [];

Creating the data set

As we go through each bird, pull out the relevant data at the start of the decade. The pie chart needs one value per bird per decade so that the end result will look like [{ color: ‘rgba(x,y,z,0.5)’, value: 65.4 }, { color: ‘rgba(x,y,z,0.5)’, value: 23.5 }]. Even if the numbers don’t add up to 100 it’ll show the proportional amounts that number takes up compared to the other(s).

001    var inputs = document.            002    getElementsByClassName(‘bird-input’);
003 for (var i = 0, len = inputs.length; i <     len;     i++) {
004        var decade1 = {
005        color: inputs[i].style.backgroundColor,
006            value: graphData.datasets[i].data[1]
007        };
008        pieData.push(decade1);
009    }

Pie markup

Your new charts will also need somewhere to go so make a new Canvas element. Chart.js’s pie and doughnut charts do not support labels so you can add an <h2> with the name of the decade. Repeat this markup for each decade (1980s, 1990s, and 2000s) changing the ID for each one.

001    <div class=”decade”>
002        <h2>1970</h2>
003    <canvas id=”pieChart” class=”pie-chart”></    004     canvas>
005    </div>

A middling position

To inject a little extra visual flair, you can position the text roughly in the middle of your pie chart. Remember that if you position a child object absolutely to a parent object that is relatively positioned then the absolutely positioned element will be relative to it’s parent, and not the page itself.

001    .decade {
002        position: relative;
003    }
004    .decade > h2 {
005        position: absolute;
006        left: 35%;
007        top: 42%;
008    }

Retina ready

Chart.js has built-in support for high-pixel-density devices, like Retina displays. So, all you have to worry about is how wide and high you would like the charts to be and it’ll internally do the maths to size them correctly (using devicePixelRatio) if viewed on high PPI devices.

001    var pies = document.            getElementsByClassName(‘pie-chart’),
002        p = pies.length;
003    while (p–) {
004        pies[p].height = window.innerHeight / 2;
005        pies[p].width = 950 / 4;
006    }

Initiate pie

With your data in place you’ll initiate it in a similar way to the line chart, the only difference being pie instead of line. Refresh your browser and you should see a cute animation as the segments spin around, hits the other side as it comes full circle and bounces; I recommend that you view www.chartjs.org/ for the full effect.

001    var pCtx = document.            getElementById(‘pieChart’).    getContext(‘2d’),
002        pie = new Chart(pCtx).Pie(pieData);

Switching out charts

Pie charts are nice but we’re going to switch it out for the lesser-used and inherently cooler doughnut chart. These types of charts display your data in the exact same way as a pie chart – the only difference is that the middle segment is cut out so our <h2>s can stand out a little bit more. Similarly, you could also use the same data to create a polar-area chart.

001    var doughnut = new Chart(pCtx).        002    Doughnut(pieData);
003    var polarArea = new Chart(pCtx2).        004    PolarArea(pieData, {
001        segmentStrokeColor: ‘rgba(0,0,0,0.5)’,
segmentStrokeWidth: 1
});

Dashboard recap

Your dashboard is functional and you’ve seen how to use a fairly complicated data set and visualise it using Chart.js. Check out the disc included with this issue for some extra bits of code to ensure colours aren’t repeated in charts and the ability to add more inputs, meaning graphs can change and reanimate on the fly.

Radar chart

The final chart type that we haven’t looked at yet is the radar chart. This accepts the same-looking data set as the line and bar charts (ie with labels). Radar charts are a really good way to show multiple data points and the differences between them within two or more data sets.

001    var radarData = {
002        labels: [‘Flying’, ‘Nesting’, ‘Eating’,     ‘Noisiness’, ‘Annoyance Rating’],
003        datasets: [{
004            data: [65,59,90,81,56]
005        }, {
006            data: [78,48,40,83,96]
007        }]
008    };
009    var radar = new Chart(ctx).Radar(radarData, {     pointDot: false });

Get charting!

So far you will have covered Chart.js’s six types of charts, it’s a neat little library that lends itself well to attractive, simple charts. It’s definitely well suited to blogs, product pages and anywhere you want some pizzazz. If you’re looking for interactive charts or a library with a bit more customisation behind it then Highcharts (www.highcharts.com/) is a good recommendation, but Chart.js is definitely a strong contender.

  • Tell a Friend
  • Follow our Twitter to find out about all the latest web development, news, reviews, previews, interviews, features and a whole more.
    • http://novalagung.com/ Noval Agung Prayogo

      I think it would be better if the code is highlighted or placed using snippet. just opinion

    • meanyack

      This is one of the good canvas charts library, but personally I prefer http://www.flotcharts.org/ as it has more flexibility.

    • cybersholt

      Would be nice if the demo worked

    • Passive Menis

      This is a terribly difficult tutorial to understand. I can’t seem to find any beginner-friendly chart.js material on the interwebs =(

    • Mathias Lindström

      Right now I’m building my own with PHP and Chart.JS (Using 5-6 languages).
      Must say, that’s alot easier and a more powerful way.