I have been digging into the Google Chart Tools lately, and have had the opportunity to utilize a few of them on client projects. This article will offer a rudimentary implementation.
The particular chart that is quite useful, especially with the shift away from Flash, is the Google GeoChart.
A Geochart is an SVG-based map of a country, continent, or region map, with colors and values assigned to specific regions. Values are displayed as a color scale, and you can specify optional hovertext for regions. The map is rendered in the browser using SVG. Note that the map is not scrollable or draggable.
To render a populated GeoChart:
- Generate the data source
- Load the Google Charting JavaScript APIs and render to the page
- Bind the data to the chart objects
- Draw the chart to the page
Generate the Data Source
First, get data to fuel the control. Here we use a simple generic dictionary:
Dictionary<string, int> data = new Dictionary<string, int>();
data.Add("UT", 0);
data.Add("Texas", 1);
data.Add("California", 2);
data.Add("New York", 3);Now to get the data into the charting objects. The Google data APIs support AJAX calls to a JSON data source which is probably a better solution than what has been done here by rendering directly to the page as a JSON object.
string MAP_DATA_FORMAT = "dataRows = [{0}];\n";
string MAP_DATA_ROW_FORMAT = "['{0}',{1}],";
string MAP_SCRIPT_FORMAT = "google.setOnLoadCallback({0});\n";
StringBuilder sbData = new StringBuilder();
StringBuilder sbScript = new StringBuilder();
foreach(KeyValuePair<string, int> d in data)
{
sbData.AppendFormat(MAP_DATA_ROW_FORMAT, d.Key, d.Value);
}
if(sbData.Length > 0)
{
// generate javascript to render the data objects to the page
sbScript.AppendFormat(MAP_DATA_FORMAT, sbData.ToString().TrimEnd(','));
sbScript.AppendFormat(MAP_SCRIPT_FORMAT, "initGlobalMap");
ClientScript.RegisterStartupScript(this.GetType(), "GlobalMap", sbScript.ToString(), true);
}Render Google Charting JavaScript/HTML
Load the Google JavaScript APIs by including the library references in the <head />:
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
Render the JavaScript necessary to handle the chart visulization:
// load the apis
google.load('visualization', '1', { 'packages': ['geochart'] });
// variable to hold our generated data source
var dataRows;
// color, style, options for the rendered control
var mapOptions = {
colors: ['#FF6F28', '#FFD7C4'],
backgroundColor: {
stroke: '#ffffff',
strokeWidth: 0,
fill: '#ffffff'
},
width: 500,
height: 312,
region: 'US',
resolution: 'provinces'
};
// initialization function that gets fired once the data source
// has been generated and everything is ready to go
function initGlobalMap()
{
// configure the map data
var mapData = new google.visualization.DataTable();
mapData.addColumn('string', 'Region');
mapData.addColumn('number', 'ID');
mapData.addRows(dataRows);
// instantiate the control/object
var geochart = new google.visualization.GeoChart(document.getElementById('chart'));
// add click (select) event listener
google.visualization.events.addListener(geochart, 'select', function ()
{
var selection = geochart.getSelection();
// pull the value from our generated data source
var id = mapData.getValue(selection[0].row, 1);
// do something wonderful
window.location = '<%= Request.Url.AbsolutePath %>?id=' + id;
});
// draw the map
geochart.draw(mapData, mapOptions);
}Last, a <div /> to contain the rendered control:
<div id="chart"></div>
Conclusion
The Google Charting APIs are a great resource if you are looking for out-of-box, supported web controls. Integration with .NET is a little more difficult due to the general lack of support, but implementation is easy and quick.
See it in action
Alltogether, packaged with a pretty bow:
<%@ Page language="c#" %>
<%@ Import namespace="System.Collections.Generic" %>
<%@ Import namespace="System.Linq" %>
<script runat="server">
protected void Page_Load(object s, EventArgs e)
{
string MAP_DATA_FORMAT = "dataRows = [{0}];\n";
string MAP_DATA_ROW_FORMAT = "['{0}',{1}],";
string MAP_SCRIPT_FORMAT = "google.setOnLoadCallback({0});\n";
StringBuilder sbData = new StringBuilder();
StringBuilder sbScript = new StringBuilder();
// get data
Dictionary<string, int> data = new Dictionary<string, int>();
data.Add("UT", 0);
data.Add("Texas", 1);
data.Add("California", 2);
data.Add("New York", 3);
// render js
foreach(KeyValuePair<string, int> d in data)
{
sbData.AppendFormat(MAP_DATA_ROW_FORMAT, d.Key, d.Value);
}
if(sbData.Length > 0)
{
sbScript.AppendFormat(MAP_DATA_FORMAT, sbData.ToString().TrimEnd(','));
sbScript.AppendFormat(MAP_SCRIPT_FORMAT, "initGlobalMap");
ClientScript.RegisterStartupScript(this.GetType(), "GlobalMap", sbScript.ToString(), true);
MapScript.Visible = true;
}
// check request
string id = Request["id"];
if(!String.IsNullOrEmpty(id))
{
SelectedItem.Visible = true;
SelectedItem.InnerHtml = String.Format(SelectedItem.InnerHtml, HttpUtility.HtmlEncode(id));
}
}
</script>
<!doctype html>
<html lang="en-US">
<head runat="server">
<title>Google GeoChart API Example - SkoNet.com</title>
<asp:placeholder id="MapScript" runat="server" visible="false">
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script type='text/javascript'>
google.load('visualization', '1', { 'packages': ['geochart'] });
var dataRows;
var mapOptions = {
colors: ['#FF6F28', '#FFD7C4'],
backgroundColor: {
stroke: '#ffffff',
strokeWidth: 0,
fill: '#ffffff'
},
width: 500,
height: 312,
region: 'US',
resolution: 'provinces'
};
function initGlobalMap()
{
var mapData = new google.visualization.DataTable();
mapData.addColumn('string', 'Region');
mapData.addColumn('number', 'ID');
mapData.addRows(dataRows);
var geochart = new google.visualization.GeoChart(document.getElementById('chart'));
google.visualization.events.addListener(geochart, 'select', function ()
{
var selection = geochart.getSelection();
var id = mapData.getValue(selection[0].row, 1);
window.location = '<%= Request.Url.AbsolutePath %>?id=' + id;
});
geochart.draw(mapData, mapOptions);
}
</script>
</asp:placeholder>
</head>
<body>
<form runat="server">
<p id="SelectedItem" runat="server" visible="false">You selected value: {0}</p>
<div id="chart"></div>
</form>
</body>
</html>