Visualizing Data With Flot

Visualizing Data with Flot

There are a lot of tutorials on how to make CSS bar graphs. But sometimes, bar graphs aren’t enough. What if our data tracks change over time and a line graph is more appropriate? Or maybe we’re not satisfied with just a bar graph. Enter Flot, ajQuery plugin that lets us make good looking graphs with ease.

In a data centric world, we often have to display large amounts of data on the web. Generally we show a table of values with headings and if we really wanted to get fancy we would use a picture of a graph. People like pictures. I like pictures. Why? Because it is far easier to interpret data when it is in visual form. However, creating a picture graph and updating it with new data can be a pain. In this tutorial, we’re going to use a jQuery plugin called Flot to create graphs on the fly.

Step 1

To start, we need some data. For this tutorial, we’re going to be using some GDP data for a few different countries I found on Wikipedia. Unfortunately the data only goes to 2003 but since this isn’t a lesson on economics, it will suffice. Let’s put the data into a simple table and add a few lines to describe it.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Flot Tutorial</title>

</head>

<body>

<div id="plotarea">
	<table>
		<caption>GDP, based on exchange rates, over time. Values in billion USDs.</caption>
		<tr>
			<td></td>
			<th scope="col">2003</th>
			<th scope="col">2002</th>
			<th scope="col">2001</th>
			<th scope="col">2000</th>
			<th scope="col">1999</th>
			<th scope="col">1998</th>
		</tr>
		<tr>
			<th scope="row">USA</th>
			<td>10,882</td>
			<td>10,383</td>
			<td>10,020</td>
			<td>9,762</td>
			<td>9,213</td>
			<td>8,720</td>
		</tr>
		<tr>
			<th scope="row">EU</th>
			<td>10,970</td>
			<td>9,040</td>
			<td>8,303</td>
			<td>8,234</td>
			<td>8,901</td>
			<td>8,889</td>
		</tr>
		<tr>
			<th scope="row">UK</th>
			<td>1,765</td>
			<td>1,564</td>
			<td>1,430</td>
			<td>1,438</td>
			<td>1,460</td>
			<td>1,423</td>
		</tr>
		<tr>
			<th scope="row">China</th>
			<td>1,575</td>
			<td>1,434</td>
			<td>1,345</td>
			<td>1,252</td>
			<td>1,158</td>
			<td>1,148</td>
		</tr>
		<tr>
			<th scope="row">India</th>
			<td>599</td>
			<td>510</td>
			<td>479</td>
			<td>457</td>
			<td>447</td>
			<td>414</td>
		</tr>
	</table>
</div>

<p>GDP, based on exchange rates, over time. Values in billion USDs.</p>

</body>
</html>

Notice that the table is contained in a div with an id of “plotarea.” The graph we will be creating later will replace the table contained inside this div. The table looks a bit ugly at the moment so let’s add some CSS to make it more presentable.

<style type="text/css">
	body { font-family: Arial, Helvetica, sans-serif; }
	table { border-collapse: collapse; }
	td, th { border: 1px solid #222; padding: 5px; }
	
	/* Fix the legend */
	.legend td, .legend th { border: 0; padding: 2px; }
</style>

You should have something that looks like this.

Data Table

Now that we have all the data in a table, we can start adding in the JavaScript that will create a graph for us. Technically, we don’t have to have a table, but it’s nice to have for two reasons:

  1. Accessibility. There are many blind web users out there and it is important to make everything on your website screen reader friendly. Screen readers cannot interpret graphs created by Flot.
  2. Degradability. A small number of web users disable JavaScript. Although this is a very small minority, it is not much more work to add a table so that they can view the data as well.

Step 2

Link the required JavaScript libraries. There are two of them, plus one more for IE support. We need to link jQuery first and then the Flot library since it depends on jQuery. Since Flot uses the canvas element to draw the graphs, we need to include the ExplorerCanvas script which emulates the canvas element in IE. Firefox, Opera and Safari users don’t need this so we’ll use conditional comments to make sure only IE users download it.

<script src="jquery.js" language="javascript" type="text/javascript"></script>
<script src="jquery.flot.pack.js" language="javascript" type="text/javascript"></script>
<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.pack.js"></script><![endif]-->

Creating a graph with Flot is quite simple because many of the options have sensible default values. This means you can create a good looking graph with minimal work, but can also tweak it to your liking. To make a basic graph, we need to specify a container element and the data to be graphed. The container element also needs to have a specified width and height, so we’ll use jQuery to set the “plotarea” div to have a width of 500px and a height of 250px.

<script language="javascript" type="text/javascript">
$(function() {
	var plotarea = $("#plotarea");
	plotarea.css("height", "250px");
	plotarea.css("width", "500px");
	$.plot( plotarea , data );
});
</script>

The first parameter is a jQuery object of the container element. The second element is a 3-dimensional array where the first child arrays are datasets and the "grandchild" arrays are ordered pairs specifying an X and Y value for a Cartesian plane. Let’s graph the GDP data for the US first.

<script language="javascript" type="text/javascript">
$(function () {
	var data = [ [[2003, 10882],
		[2002, 10383],
		[2001, 10020],
		[2000, 9762],
		[1999, 9213],
		[1998, 8720]] ];
	
	var plotarea = $("#plotarea");
	plotarea.css("height", "250px");
	plotarea.css("width", "500px");
	$.plot( plotarea , data );
});
</script>
Single Graph

The data table we had before should be replaced with a nice look graph. As you can see, the array containing the dataset is contained in another parent array. To graph another dataset, we just add it as another element to the parent array. Let’s add the data for the other countries we had in our table.

var data = [
	[[2003, 10882],
	[2002, 10383],
	[2001, 10020],
	[2000, 9762],
	[1999, 9213],
	[1998, 8720]],
	
	[[2003, 10970],
	[2002, 9040],
	[2001, 8303],
	[2000, 8234],
	[1999, 8901],
	[1998, 8889]],
	
	[[2003, 1795],
	[2002, 1564],
	[2001, 1430],
	[2000, 1438],
	[1999, 1460],
	[1998, 1423]],
	
	[[2003, 1575],
	[2002, 1434],
	[2001, 1345],
	[2000, 1252],
	[1999, 1158],
	[1998, 1148]],
	
	[[2003, 599],
	[2002, 510],
	[2001, 479],
	[2000, 457],
	[1999, 447],
	[1998, 414]]
];
Multi Graph

We now have a fairly good looking graph, but we don’t know which line is which country! What we need is a legend. Fortunately, Flot supports this and is a matter of putting our datasets in a JSON object and adding a label element.

var data = [
	{
		label: "USA",
		data: [[2003, 10882],
			[2002, 10383],
			[2001, 10020],
			[2000, 9762],
			[1999, 9213],
			[1998, 8720]]
	},
	
	{
		label: "EU",
		data: [[2003, 10970],
			[2002, 9040],
			[2001, 8303],
			[2000, 8234],
			[1999, 8901],
			[1998, 8889]]
	},
	
	{
		label: "UK",
		data: [[2003, 1795],
			[2002, 1564],
			[2001, 1430],
			[2000, 1438],
			[1999, 1460],
			[1998, 1423]]
	},
	
	{
		label: "China",
		data: [[2003, 1575],
			[2002, 1434],
			[2001, 1345],
			[2000, 1252],
			[1999, 1158],
			[1998, 1148]]
	},
	
	{
		label: "India",
		data: [[2003, 599],
			[2002, 510],
			[2001, 479],
			[2000, 457],
			[1999, 447],
			[1998, 414]]
	}
];
Graph with Legend

Step 3

I mentioned before that although Flot has many sensible defaults. While they’re probably be fine for most people, the legend partially obscures some of the data. Flot has a third parameter for passing in options in a JSON object.

$.plot( plotarea , data, options );

To make the data at the far end of the graph a little more visible, we’ll adjust the background opacity and margins of the legend.

var options = {
	legend: {
		show: true,
		margin: 10,
		backgroundOpacity: 0.5
	}
};
Options

Some people (like me) like being able to see exactly where the data points are, so let’s specify in the options to mark each point with a circle of a specified radius.

var options = {
	legend: {
		show: true,
		margin: 10,
		backgroundOpacity: 0.5
	},
	points: {
		show: true,
		radius: 3
	}
};
Points

Great, we have data points, but where’d the lines go?! Let’s explicitly turn them back on.

var options = {
	legend: {
		show: true,
		margin: 10,
		backgroundOpacity: 0.5
	},
	points: {
		show: true,
		radius: 3
	},
	lines: {
		show: true
	}
};
Points with Lines

Our final code looks something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Flot Tutorial</title>

<style type="text/css">
	body { font-family: Arial, Helvetica, sans-serif; }
	table { border-collapse: collapse; }
	td, th { border: 1px solid #222; padding: 5px; }
	
	/* Fix the legend */
	.legend td, .legend th { border: 0; padding: 2px; }
</style>

<script src="jquery.js" language="javascript" type="text/javascript"></script>
<script src="jquery.flot.pack.js" language="javascript" type="text/javascript"></script>
<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.pack.js"></script><![endif]-->

<script language="javascript" type="text/javascript">
$(function () {
	var data = [
		{
			label: "USA",
			data: [[2003, 10882],
				[2002, 10383],
				[2001, 10020],
				[2000, 9762],
				[1999, 9213],
				[1998, 8720]]
		},
		
		{
			label: "EU",
			data: [[2003, 10970],
				[2002, 9040],
				[2001, 8303],
				[2000, 8234],
				[1999, 8901],
				[1998, 8889]]
		},
		
		{
			label: "UK",
			data: [[2003, 1795],
				[2002, 1564],
				[2001, 1430],
				[2000, 1438],
				[1999, 1460],
				[1998, 1423]]
		},
		
		{
			label: "China",
			data: [[2003, 1575],
				[2002, 1434],
				[2001, 1345],
				[2000, 1252],
				[1999, 1158],
				[1998, 1148]]
		},
		
		{
			label: "India",
			data: [[2003, 599],
				[2002, 510],
				[2001, 479],
				[2000, 457],
				[1999, 447],
				[1998, 414]]
		}
	];
	
	var options = {
		legend: {
			show: true,
			margin: 10,
			backgroundOpacity: 0.5
		},
		points: {
			show: true,
			radius: 3
		},
		lines: {
			show: true
		}
	};
	
	var plotarea = $("#plotarea");
	plotarea.css("height", "250px");
	plotarea.css("width", "500px");
	$.plot( plotarea , data, options );
});
</script>
</head>

<body>

<div id="plotarea">
	<table>
		<caption>GDP, based on exchange rates, over time. Values in billion USDs.</caption>
		<tr>
			<td></td>
			<th scope="col">2003</th>
			<th scope="col">2002</th>
			<th scope="col">2001</th>
			<th scope="col">2000</th>
			<th scope="col">1999</th>
			<th scope="col">1998</th>
		</tr>
		<tr>
			<th scope="row">USA</th>
			<td>10,882</td>
			<td>10,383</td>
			<td>10,020</td>
			<td>9,762</td>
			<td>9,213</td>
			<td>8,720</td>
		</tr>
		<tr>
			<th scope="row">EU</th>
			<td>10,970</td>
			<td>9,040</td>
			<td>8,303</td>
			<td>8,234</td>
			<td>8,901</td>
			<td>8,889</td>
		</tr>
		<tr>
			<th scope="row">UK</th>
			<td>1,765</td>
			<td>1,564</td>
			<td>1,430</td>
			<td>1,438</td>
			<td>1,460</td>
			<td>1,423</td>
		</tr>
		<tr>
			<th scope="row">China</th>
			<td>1,575</td>
			<td>1,434</td>
			<td>1,345</td>
			<td>1,252</td>
			<td>1,158</td>
			<td>1,148</td>
		</tr>
		<tr>
			<th scope="row">India</th>
			<td>599</td>
			<td>510</td>
			<td>479</td>
			<td>457</td>
			<td>447</td>
			<td>414</td>
		</tr>
	</table>
</div>

<p>GDP, based on exchange rates, over time. Values in billion USDs.</p>

</body>
</html>

Concluding Thoughts

There are many possibilities with Flot. The Flot API details all the different options that are available for tweaking your graphs including specifying different graph types, colors, axes, and even enabling interactive features like selection and zooming. Another possibility is to make the entire thing fully dynamic and generate the JavaScript code dynamically with data from a database using PHP.

  • Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://insicdesigns.com insic

    this is very use tutorial. i love it. I have to use it in my web application im working right now, perfect timing.

  • Julien L

    Nice tuts ! I think in the growing world of web app’, it coul be very usefull for enterprises.
    Thanks !

  • http://www.ben-griffiths.com Ben Griffiths

    This is absolutely fantastic – I didn’t even know of this tool, it looks great. Thanks for showing us how to use it :)

  • http://www.technoboria.com/ Jim

    I second the comment regarding useful for corporates, they love visualizing data and htis is perfect especially since it is JQ

  • http://iamgp.com Gareth

    Great tutorial, I just wish that you didn’t have to enter the data in twice..

  • realone

    if data are negative,result will be wrong

  • Chris Gedrim

    Great tutorial, but is there any way to get the data from the table?

    Could each td be iterated through to get the data without setting id’s or class’s?

    If so then you could pull data using PHP/ASP and plot in semi-realtime.

  • http://www.psychologyace.tk Adam

    Not the normal sort of tutorial I must say, but it’s great how Nettuts shows diversity. I love this tutorial and think it gives a great perspective to the the site and it’s ethos.

    Great work.

  • http://www.freshclickmedia.com Shane

    I’ve used flot on a recent project, and found it to be pretty impressive.

  • http://www.snagr.co.uk Mark Henderson

    Excellent tutorial, exactly what I have been looking to get into, thanks you’ve saved me so much research time!!!

    More Jquery / Asp.net tutorials like this please!!!!

  • http://dalsvaag.net Christian Dalsvaag

    Wow, this tutorial is on an excellent subject. I’ve never even heard of this tool before. Thank you! Good job.

  • http://www.jamessmith.co.uk JamesS

    Great find, thanks.

    I have been using FusionCharts recently, which is really excellent too – It’s based on Flash and XML rather than jQuery, but I can highly recommend it: http://www.fusioncharts.com/ … It’s almost infinitely customisable.

    James

  • John

    Looks nice.

    But with other similar tools I want to see examples of it handling thousands of data points.

  • Patrick

    yay, nice tutorial. very helpful for graphical site statistics :D

  • http://instantsolve.net Thomas Milburn

    Another great tutorial especially as you’ve covered the issues of accessibility and usability by users who don’t have JavaScript.

    Flot looks like a neat tool for producing on the fly graphs, I’ll certainly remember this for projects in future. I’ve also been doing some research on the canvas element. People are doing loads of other wicked stuff with it like this:
    http://azarask.in/projects/algorithm-ink/

  • http://laminbarrow.com Lamin Barrow

    WOW, what a cool and interesting tut. This is uncharted territory man. Many thanks. :)

  • http://laminbarrow.com Lamin Barrow

    There is also another JS library call Raphael (http://raphaeljs.com/) that does similar things as this Jquery Plugin for those of you interested in checking out what other options are available.

  • http://www.furleydelphia.com Furley

    very interesting.

    google charts is faster and easier though. unless you feel like splitting hairs over the design of the chart, id use googles API.

  • Jeff

    awsome, this is great. just what i needed for my current asp.net mvc project (wich now ships with jquery :)). I was trying to write this myself, next time i will remember to look for plugins first.

  • http://www.receitasdomundo.net/ rrealinho

    Wow. Excellent tutorial!

  • http://twitter.com/phluxor Robert

    Totally deserves a tweet :) nice job…

  • http://www.CodeSpanish.com Pablo Matamoros

    Awesome!!!

    Javascript keeps surprising me…. Who dares to say that client scripting is not a powerful tool! And free ;P

  • Pingback: 2008 October 24 - Links for today « My (almost) Daily Links

  • http://stevejamesson.com Steve

    Very nice! Gonna come in handy for a few projects I’ve got cooking now!

  • http://jimjamesson.com/category/photoshop-tutorials/ Jim Jamesson

    Wow this is awesome! We are sooo trying this today :)

  • Pingback: JeremiahTolbert.com » Blog Archive » links for 2008-10-25

  • http://freewarecollection.co.cc Freeware Collection

    How beautiful it is. It’s really wonderful. Thank you very much.

  • Pingback: mskari.org » Daily Summary 2008-10-24

  • http://URL(Optional) Khurram

    Really KOOOll 0-o : )

  • http://freepsds.wordpress.com montana flynn

    wow that was great! thanks a bunch

  • http://www.ravewarrior.com Reza Budi Prabowo

    this is just what i need. thanks!

  • http://www.muneefhameed.com muneefvc

    Bravo!
    just what i am looking for ..!!

  • http://usrexman.wordpress.com uSreX-man

    Thanx very much!!!Makasih banget y source code nya!!!
    God Bless You….!!!!He….!!!

    uSreX-man

  • highblood

    Hi James! First of all thanks for sharing this great tutorial. I have a couple of question regarding this tutorial since I wan to apply it in my work.

    1) What would be the code if the countries be like check boxes where I have the option to choose which country I to appear on the chart?

    2) How do you show up the actual values when I mouse-over certain points on the data?

    Thanks in advance

  • http://www.athanne.com Busby

    Wow! Great! I have tried to create a bar graph using php with one of our client but im not that happy with the results. Maybe i will use ajax next time

  • dh

    Very, very cool. One question: Does it print too?

  • Gatot Wibowo

    Terima kasih…. how does it print in paper?

  • Pingback: Visualizing Data with Flot - NETTUTS | Enjoy News, Feeds & Share All Your Favorite Media Online With The Rest Of the World… Video, TV, Shows, Music, Audio, Pictures, Images, Games, News, Feeds, Links, www.CLHMedia.com

  • http://siubie.zxq.net/wordpress siubie

    flot weakpoint is the graph cannot be printed CMIIW

    but how to dynamically add data from php to flot ?

  • http://www.fruuit.com/graphs/one/?comment Bugsy

    Installed FLOT over the last couple days. AMAZING!

    I see that Siubie asked about how to add data from php….

    I have an SQL query that draws the data and insrts it into the data tag using repeat around [x1, y2], through all of the records. And boom live updated data.

    I made a few charts so far based of my Daily Fruit blog…

    http://www.fruuit.com/graphs/one/

  • http://30noohe.wordpress.com Mehran Khajavi(sinoohe)

    It’s so great and powerful
    thanks again :D

  • Spike

    Great article! One question… is there a way to save the graph as a PNG? When I try to view the image all i see is a blank “canvas” image.

    Thanks!

  • http://marcust.com MarcusT

    I like the article, but I don’t like the way it duplicates the data within the table AND JavaScript – this is completely unnecessary! Instead, the code should have read the data from the table and displayed it as a graph – in fact, it would make sense to encapsulate the functionality into a reusable plugin which could be applied to any data table, while accepting configuration parameters of course. Perhaps this article could be revised or revisited in a new article to show how this could be done? I know how, but it would be a useful tutorial for many.

  • http://www.tomasroggero.com.ar Tom

    I made an interesting piece of code.

    var myways = [];
    var mydata = [];
    $(“#src”).find(“th[scope='col']“).each(function(){
    myways.push($(this).html());
    });
    $(“#src tr”).each(function(){
    var thiszone;
    var zone = $(this).find(“th[scope='row']“).html();
    var zonex = [];
    $(this).find(“td”).each(function(){
    var aval = parseInt($(this).html());
    zonex.push(aval);
    });
    if(zone != null){
    var zonedata = [];
    for(var i=0;i<myways.length;i++){
    zonedata.push([myways[i], zonex[i]]);
    }
    thiszone = {label: zone, data: zonedata};
    mydata.push(thiszone);
    }
    });

    Now, you don’t have to write all data stuff, just do the table, assign an ID and you will see the results! In order to make this thing work, you need to have numbers without commas or dots. And add the class row to labels and class col to data labels. Enjoy!

  • http://www.wpdigger.com/ wpdigger

    Nice tuts ! I think in the growing world of web application.
    Thanks for showing us how to use it :)

  • rajan

    Great man…i tried so many other javascript framework,,,but flot is so simple and useful,…thanks for tutorial

  • diego

    hii
    can flot plot live streaming charts like stock charts without completely reloading itself.please do help me with the code i am new to flot. thankyou

  • Jeremie

    Hi, great article. I found this tutorial useful too:
    http://www.eremiya.net/
    If it could help…

  • http://www.unizoe.com Rajesh

    thanks buddy, what a plugin, nice tutorial also….. I was looking to start using this plugin and you gave me excellent guidelines…..
    Thanks again….

  • http://www.myswimlog.com Tony Murphy

    Hi,

    Very useful. I am using Flot in a Web App for Swimmers and this has helped clarify the setting of the various options.

    cheers
    Tony