How-to save Google Charts visualizations to an image file in a user-friendly way

H

Personally I love Google Charts API. It offer so much potential for visualizing information. And all that, for free.

I use Google Charts professionally to visualize online marketing statistics on Marketingfacts, the largest online marketingblog in the Netherlands.

Despite all it’s great features, Google Charts also has some limitations. One of those is the ability to save charts to images, preferably in it’s current state. Kind of frustrating to see that Google does use it themselves on http://www.thinkwithgoogle.com/mobileplanet/en/, but it’s not featured in the API.

So, why don’t you use Google Image Charts?

Image Charts was a great way to accomplish this, but unfortunately Google deprecated this as of April 20, 2012. Although it should stay continue to work, I couldn’t get it to work with my Google Charts data anymore.

Turn an interactive chart into an image

After a few searches around the web, and browsing through several tickets in Google Code (12), I eventually stumbled onto this great article by Riccardo Govoni.

As Riccardo entails, the main trick to make ‘image serialization’ work is to first convert the SVG chart into a canvas element and extract its contents as base64 encoded image using canvas.toDataURL.

Summarizing Riccardo’s solution:

  • Extract the svg code for the chart you want to serialize
  • Using the canvg svg-to-canvas converter, you transform the svg instructions into a canvas rendering
  • Extract the image data (as a base64 encoded string) and send it to the browser so it can be downloaded

This all seems very technical but if you look at the sample page it all becomes clear.

Great!

The only problem is that the download which it generated doesn’t have a user-friendly name and extensions, which make them unusable for normal users. Fortunately I found this blogpost by Jonathan Greene in which he explains his solution to offer the download in a user-friendly way, rather than this:

I’ve converted Jonathan’s .js file to the following script:

function saveAsImg(chartContainer, pngfilename) {
var chartArea = chartContainer.getElementsByTagName(‘svg’)[0].parentNode;
var svg = chartArea.innerHTML;
var doc = chartContainer.ownerDocument;
var canvas = doc.createElement(‘canvas’);
canvas.setAttribute(‘width’, chartArea.offsetWidth);
canvas.setAttribute(‘height’, chartArea.offsetHeight);
canvas.setAttribute(
‘style’,
‘position: absolute; ‘ +
‘top: ‘ + (-chartArea.offsetHeight * 2) + ‘px;’ +
‘left: ‘ + (-chartArea.offsetWidth * 2) + ‘px;’);
doc.body.appendChild(canvas);
canvg(canvas, svg);
var data = canvas.toDataURL(“image/png”);
canvas.parentNode.removeChild(canvas);
data = data.substr(data.indexOf(‘,’) + 1).toString();

var dataInput = document.createElement(“input”) ;
dataInput.setAttribute(“name”, ‘imgdata’) ;
dataInput.setAttribute(“value”, data);

var nameInput = document.createElement(“input”) ;
nameInput.setAttribute(“name”, ‘name’) ;
nameInput.setAttribute(“value”, pngfilename + ‘.png’);

var myForm = document.createElement(“form”);
myForm.method = ‘post’;
myForm.action = ‘HERE PUT THE URL TO YOU SAVEME FILE’;
myForm.appendChild(dataInput);
myForm.appendChild(nameInput);

document.body.appendChild(myForm) ;
myForm.submit() ;
document.body.removeChild(myForm) ;

}

For the actual action you need to send the right container to the javascript. You can do this as follows:

<a href=”#” onClick=”saveAsImg(document.getElementById(‘THE CHART CONTAINER’), ‘NAME OF THE FILE WHICH IS OFFERED FOR DOWNLOAD’);”>

That should do the trick! Don’t forget to setup a saveme file as Jonathan explains in his blog.

You can view some live examples here:

http://www.marketingfacts.nl/statistieken/detail/online-consumentenbestedingen

http://www.marketingfacts.nl/statistieken/detail/populariteit-sociale-media