Google quietly released their new charts API late last year. It was originally an internal project used by their Video and Finance services until they decided to make it public. Google consistently provides such elegant and effective solutions to common problems. Their charts API is no exception. It comes about as close to the Shangri-La of software-as-a-service as we can get right now.
Ruby developers have enjoyed many different charting libraries over the past few years. Projects like Sparklines, Gruff, and SVG::Graph definitely got the job done, but many of them also relied on RMagick, thus dooming us to a sleepless, frustrating night spent attempting to install the medieval monster which is ImageMagick.
No longer are we doomed to such futile efforts, however. What if generating a chart were as easy as constructing a URL? No state to track and no nasty XML to pass around. In the immortal words of a certain Starfleet captain, Google has "made it so" and given us a way to construct charts on the fly through the simplicity of the HTTP protocol:
- No additional software to install
- Cross-browser compatible
- Works on any platform that supports HTTP
- Google can serve our charts OR we can download and serve them ourselves
- Generous usage policy
Not only is the API a delight to use, but the charts look fantastic too.
For example, a pie chart:
http://chart.apis.google.com/chart?cht=p3&chd=t:65,35&chs=150x100
Bar charts are just as easy:
http://chart.apis.google.com/chart?cht=bvg&chs=
200x125&chd=t:80,50,70%7C100,90,50&chco=cc0000,00aa00
A linear chart with a background gradient just means the URL will be a tad longer:
http://chart.apis.google.com/chart?cht=lc&chd=
s:pqokeYONOMEBAKPOQVTXZdecaZcglprqxuux393ztpoonkegg
jp&chco=FF0000&chls=4.0,3.0,0.0&chxt=x,y&chxl=
0:%7C1%7C2%7C3%7C4%7C5%7C1:%7C0%7C50%7C100&chs=200
x125&chf=c,lg,45,ffffff,0,76A4FB,0.75%7Cbg,s,EFEFEF
We can even generate color-coded maps:
http://chart.apis.google.com/chart?chco=f5f5f5,ed
f0d4,6c9642,365e24,13390a&chd=s:fSGBDQBQBBAGABCBDAKLCD
GFCLBBEBBEPASDKJBDD9BHHEAACAC&chf=bg,s,eaf7fe&chtm=usa&
chld=NYPATNWVNVNJNHVAHIVTNMNCNDNELASDDCDEFLWAKSWIORKYMEO
HIAIDCTWYUTINILAKTXCOMDMAALMOMNCAOKMIGAAZMTMSSCRIAR&chs=44
0x220&cht=t
The charts can get pretty complex, but the URL is still manageable:
http://chart.apis.google.com/chart?cht=r&chs=200x200&chd=
s:voJATd9v,MW9BA9&chco=FF0000,FF9900&chls=2.0,4.0,0.0|
2.0,4.0,0.0&chxt=x&chxl=0:|0|45|90|135|180|225|270|315&chxr
=0,0.0,360.0&chg=25.0,25.0,4.0,4.0&chm=B,FF000080,0,1.0,5.0|
B,FF990080,1,1.0,5.0|h,0000FF,0,1.0,4.0|h,3366CC80,0,0.5,5.0|
V,00FF0080,0,1.0,5.0|V,008000,0,5.5,5.0|v,00A000,0,6.5,4
Pretty stuff, isn't it? The URL parameters can be hard to decipher without reading the docs, but load time is very snappy and the interface couldn't be simpler.
Think of the possibilities here.
- Embed the chart in an existing HTML page:
<img src="http://chart.apis.google.com/chart?cht=p3&chd=t:65,35&chs=500x200"/>
- Use the chart in RHTML or HAML markup:
<%= image_tag "http://chart.apis.google.com/chart?cht=p3&chd=t:65,35&chs=500x200" %>
- Download the chart as a PNG file:
wget -O chart.png "http://chart.apis.google.com/chart?cht=p3&chd=t:65,35&chs=500x200"
If we don't like the idea of relying on Google's servers to render our chart, it's easy enough to transfer the image to our own server. For example, here's a simple Capistrano task that grabs the chart and uploads it to the deploy server:
set :chart_url, "http://chart.apis.google.com/chart?cht=p3&chd=t:65,35&chs=500x200"
task :update_chart do
`wget -O chart.png #{chart_url}`
put File.read("chart.png"), "#{deploy_to}/chart.png"
`rm -f chart.png`
end
Basic Parameters
The simplicity of sending a URL to generate a chart is a good thing, but what parameters make up the URL? A full API reference is available on Google's site, but we can build a surprising number of charts using only a few simple parameters.
The base URL for generating a chart is always:
http://chart.apis.google.com/chart?
There are only three parameters required by Google to construct a chart: the type of chart, the size of the chart, and the data for the chart.
Chart type is specified with the "cht" parameter. There are literally dozens of different chart types, but the most common are line charts ("lc"), horizontal bar charts ("bhs") and vertical bar charts ("bvs"). To generate a line chart, our URL would be:
http://chart.apis.google.com/chart?cht=lc
We have two parameters missing here: chart size and chart data. Let's add those next. Chart size ("chs") takes the width and height of the chart in integer values. For example, to make our chart 100 pixels wide and 50 pixels tall:
http://chart.apis.google.com/chart?cht=lc&chs=100x50
Finally, let's add our chart data ("chd"). There are four different ways of encoding data for Google, but the simplest is text encoding. To tell Google that we want to use text encoding, we add "t:" as the prefix for our data:
http://chart.apis.google.com/chart?cht=lc&chs=100x50&chd=t:
Text encoding uses one or more floating point numbers in the range from zero to one hundred. The closer the number is to one hundred, the higher the value on the chart. If the values being charted exceed one hundred, we're responsible for scaling them down to the correct range. To plot three points on our chart, the URL would be:
http://chart.apis.google.com/chart?cht=lc&chs=100x50&chd=t:25,75,50
The resulting chart looks like this:
With these three parameters in hand, we can generate nearly any chart we would ever need. What if we want to get fancier, though? The API allows for colors, gradients, legends, etc. There are too many additional options to cover here, but check out the well-written API reference to learn more.
Easy Chart Generation with gchartrb
We've seen that constructing the URL with basic parameters is straightforward enough, but the code to generate a single chart of moderate complexity is going to violate the DRY principle (Don't Repeat Yourself). When we want to generate multiple charts on the same page, the duplicate code will become nightmarish as we copy and paste.
To mitigate this, we start extracting bits and pieces of our code into classes and methods. Perhaps we'll have a single method that takes our chart data and parameterizes it for the URL. A second method could handle picking the right color for the chart based on a pre-defined name. A third could generate a legend. What we're talking about here is a wrapper for Google's API that gives us a friendly interface.
Fortunately, we don't have to reinvent the wheel. Deepak Jois has written just such a wrapper for the API. His gem, called gchartrb, provides a clean, concise way to generate chart URLs. The first step to using the gem is installing it:
gem install gchartrb
Now we get to open up our favorite editor and start coding. This is how we would generate a simple bar chart:
require 'rubygems'
require 'google_chart'
GoogleChart::BarChart.new('800x200', 'My Chart', :vertical) do |bc|
bc.data 'Trend 1', [5,4,3,1,3,5], '0000ff'
bc.data 'Trend 2', [1,2,3,4,5,6], 'ff0000'
bc.data 'Trend 3', [6,5,4,4,5,6], '00ff00'
puts bc.to_url
end
Executing this code would result in:
http://chart.apis.google.com/chart?chtt=Bar+Chart&cht=
bvg&chs=800x200&chco=0000ff,ff0000,00ff00&chd=s:yoeKey,KU
eoy9,9yooy9&chdl=Trend+1|Trend+2|Trend+3
Note that calls to the data
method take a name (for use in an optional legend), an array of data, and a color expressed in hex. We don't have to worry about the correct format for these parameters: the library handles that complexity for us.
The size, name, and orientation of the chart (vertical vs. horizontal) is given when the BarChart class is instantiated:
BarChart.new('800x200', 'Bar Chart', :vertical)
Again, the correct parameters are generated by the library, saving us the trouble. Calling to_url
gives us the URL for our chart, ready to be embedded in a page.
For a relatively young gem, gchartrb is surprisingly complete. It supports generation of basic line, pie, and bar charts of course, but also Venn diagrams and scatter plots. Any of the charts it generates can also be prettified with gradients, backgrounds, fills, stripes, multi-color legends, and more. Check out the web site for further documentation on what can be done.
Conclusion
Google's charts API is an amazing tool, and gchartrb makes it even better by providing a clean wrapper around it. We can now generate charts in our Rails applications without having to natively compile a shred of additional software. Now that's cool.