Thursday, July 31, 2008

Google Visualization

Google Visualization is an API where you can feed your data to it and it will produce for you a "visualization" of your data; such as in a pie-chart, bar-chart, line-chart, and even some more complex visualization rendering. In other words, if you have structured data (dynamic or static), you can let Google handle the rendering of its visualization for you (instead of making a screen capture/image in a desktop app and including it in your web app/site).


Here is an example (taken from Google pie-chart code example) on how to render a pie chart about daily activities. From this basic code, we can customize the code to our liking, including displaying dynamic data.


<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["piechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows(5);
data.setValue(0, 0, 'Work');
data.setValue(0, 1, 11);
data.setValue(1, 0, 'Eat');
data.setValue(1, 1, 2);
data.setValue(2, 0, 'Commute');
data.setValue(2, 1, 2);
data.setValue(3, 0, 'Watch TV');
data.setValue(3, 1, 2);
data.setValue(4, 0, 'Sleep');
data.setValue(4, 1, 7);

var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240, is3D: true, title: 'My Daily Activities'});
}
</script>
</head>

<body>
<div id="chart_div"></div>
</body>
</html>

The result (you can click on the chart btw - and get some details):


As I mentioned above, customization is easy. With dynamic data that comes from the server, as long as you can form your data to conform with the javascript data.addColumn format, you are set! Here is an example using data coming from ASP.NET MVC ... (or using JSON is also very easy)

<script type="text/javascript">
google.load("visualization", "1", {packages:["piechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows(<%=(ViewData["MyTasks"] as List<Task>).Count() %>);
<%
int i = 0;
foreach (var task in (ViewData["MyTasks"] as List<Task>))
{
int j = 0;
%>
data.setValue(<%=i %>, <%=j %>, "<%=task.TaskName.Length > 15 ? task.TaskName.Substring(0, 15) + " ..." : task.TaskName%>");
<%j++; %>
data.setValue(<%=i %>, <%=j %>, <%=task.Hours %>);
<%i++; %>
<%
}
%>
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240, is3D: true, title: 'My Daily Activities'});
}
</script>

Now, if you are using ASP.NET web-form, is it not that easy to get your data out from your code-behind and expose it to the javascript api of Google Visualization. In this case you may need to expose your object as a protected property of your control/page so it can be accessible.

Nevertheless, once you are at the point where your data is accessible, sending your data to Google and getting a visualization back is a breeze (and fast too).

Cool, huh? Now, let's look at the code in more detail:

<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
...
This part of the code is where you reference Google's API in your code. There is no javascript to download etc, and this is all you need to do to make the API available for you. Now, in a way this is cool, because you don't need to worry about the javascript itself, less file to maintain, etc. But, it also means that there is no intellisense. I don't think it is that big of a deal, since the code you are writting will be pretty concise anyway.


...
google.load("visualization", "1", {packages:["piechart"]});
google.setOnLoadCallback(drawChart);
...
This section of code is what telling the API about what visualization you want to use (such as "piechart") and instantiate it, then it calls the method "setOnLoadCallback" passing in a method "drawChart"; which that puts the data together send it to the API to be drawn. The method "drawChart" is not a Google method. It is a regular javascript method and you can call it whatever you want (such as "myMethod" or "whatever") and as long as it is consistent in its uses, you will be fine.


...
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows(5);
data.setValue(0, 0, 'Work');
data.setValue(0, 1, 11);
...
The example we are looking at is using a "DataTable" type to hold our data. This is probably the simplest way of holding our data to be sent to the visualization engine. I am not sure if there are any other data structure available from Google, but so far I have not had any needs to go beyond what DataTable has been able to provide. Anyway, this section of code is basically for putting our data together into the DataTable object "data". DataTable is basically an array. So when we are setting the values using setValue method, we are setting the data based on a specifiec coordinate (row/column). The method setValue takes in these parameters: row, column, value. You can have as many columns as you want as long as you define them - using addColumn method - before putting data into the DataTable.

...
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
...
This code is pointing out to Google Visualization on where to draw the chart. I created a div space in my HTML and gave it an id ("chart_div").

Click here to go to Google Visualization Gallery.

2 comments:

Maru said...

Thank for this topic.
I am a beginning for google visualization. I would like to show graph using google visualization. Data is on array list how can I send my data to datatable

Johannes Setiabudi said...

Are you using webform or mvc? As long as you can iterate through your array list, you should be able to to follow code example #2.

So if I put my "task" data from example #2 into an arraylist instead of regular List, it would be something like this:

<%
int i = 0;
foreach (var item in myArrayList))
{
int j = 0;
%>
data.setValue(<%=i %>, <%=j %>, "<%=item.TaskName.Length > 15 ? item.TaskName.Substring(0, 15) + " ..." : item.TaskName%>");
<%j++; %>
data.setValue(<%=i %>, <%=j %>, <%=item.Hours %>);
<%i++; %>
<%
}
%>