When I attempt to load a Google Chart in node.js, nothing happens.
I tried loading the first example from the line chart docs in both zombie.js and jsdom, but the chart never loads in either case.
The end goal is to retrieve the SVG data of the generated chart for export into an image or PDF. So if an alternate method (server side using node.js or PHP) to achieve this is possible, I'm open to suggestions.
NOTE: I have successfully generated a images of a few charts using gChartPhp, but the requirements of this project state that the embedded version be the interactive version provided by the current API and the exported version be visually IDENTICAL to the embedded one (without being interactive, obviously).
Edit: I tagged PhantomJS, since that is the solution with which I ultimately went.
Sorry for the lack of links, but the spam prevention mechanism will only allow me to post 2.
It wasn't the ideal solution, but I found an alternative to node.js for accomplishing the same end goal in PhantomJS. Simply create an HTML file containing the chart (test.html) and like node.js, create a JS file containing your code (test.js). Then run your JS file with PhantomJS.
In your JS file, open your HTML file as a webpage, then render it, either saving the image buffer to a file:
var page = require('webpage').create();
page.open('test.html', function () {
page.render('test.png');
phantom.exit();
});
Then run it:
phantomjs test.js
To dynamically create a chart, create the following JS file (test2.js):
var system = require('system');
var page = require('webpage').create();
page.onCallback = function(data)
{
page.clipRect = data.clipRect;
page.render('test.png');
phantom.exit();
};
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js', function()
{
page.includeJs('https://www.google.com/jsapi', function()
{
page.evaluate(function(chartType, data_json, options_json)
{
var div = $('<div />').attr('id', 'chart').width(900).height(500).appendTo($('body'));
google.load("visualization", "1",
{
packages:[chartType == 'GeoChart' ? 'geochart' : 'corechart'],
callback: function()
{
data_arr = $.parseJSON(data_json);
data = google.visualization.arrayToDataTable(data_arr);
options = $.parseJSON(options_json);
chart = new google.visualization[chartType]($(div).get(0));
google.visualization.events.addListener(chart, 'ready', function()
{
window.callPhantom(
{
clipRect: $(div).get(0).getBoundingClientRect()
});
});
chart.draw(data, options);
}
});
}, system.args[1], system.args[2], system.args[3]);
});
});
Then run it:
phantomjs test2.js LineChart '[["Date","Steve","David","Other"],["Dec 31",8,5,3],["Jan 1",7,10,4],["Jan 2",9,4,3],["Jan 3",7,5,3]]' '{"hAxis.slantedText":true}'
phantomjs test2.js PieChart '[["Employee","Calls"],["Steve",31],["David",24],["Other",13]]' '{"is3D":true}'
phantomjs test2.js GeoChart '[["State","Calls"],["US-CA",7],["US-TX",5],["US-FL",4],["US-NY",8]]' '{"region":"US","resolution":"provinces"}'
To get the image data from an external script, make a copy of test2.js (test3.js) and change
page.render('test.png');
to
console.log(page.renderBase64('png'));
Then call it (from PHP, for example):
<?php
$data = array(
array("Employee", "Calls"),
array("Steve", 31),
array("David", 24),
array("Other", 13)
);
$options = array(
"is3D" => true
);
$command = "phantomjs test3.js PieChart '" . json_encode($data) . "' '" . json_encode($options) . "'";
unset($output);
$result = exec($command, $output);
$base64_image = implode("\n", $output);
$image = base64_decode($base64_image);
?>
NOTE: Looking back on this whole process, the problem I was having with node.js was possibly that I didn't setup callbacks or timeouts to wait until the charts were "ready".