您的位置:首页 > Web前端 > JavaScript

PhantomJS: a new way for running Highcharts on the server side

2014-09-17 06:07 661 查看
http://208.71.46.190/search/srpcache?ei=UTF-8&p=a+new+way+for+running+Highcharts+on+the+server+side+by+Joe+Kuan&fr=yfp-t-901&fp=1&u=http://cc.bingj.com/cache.aspx?q=a+new+way+for+running+Highcharts+on+the+server+side+by+Joe+Kuan&d=4737680985883949&mkt=en-US&setlang=en-US&w=evARA1E6ylpqcqHf-_-uNMllGP8O3ulm&icp=1&.intl=us&sig=OIxQ6YL_0PGkoQAnNV7AuA--


PhantomJS: a new way for running Highcharts on
theserver side

by Joe Kuan

While I was writing up a survey for running Highcharts on the server side which
accounts for 3 approaches:

Xvfb + web browser on server side (Unix only)

Rhino + Env.js (Java solution)

Node/Node.js + Highcharts NodeJs module (Javascript solution)

I didn’t realise there is another one, PhantomJS (thanks
to the remark by Torstein
Hønsi).

PhantomJS is a headless webkit which makes running JavaScripts
on the server side a lot easier and no more issue on DOM implementations. It’s like running a
HTML5 browser on the server without it’s user interface. There are several tasks which comes very handy with PhantomJS and server side SVG
rendering is one of them.

Running PhantomJS is as simple as launching a command on the server side like:
phantomjs exportLineChart.js seriesData.js


Lets see how we can create exportChart.js. First of all, load up the required basic modules. The most interesting is the 2nd line, which loads up a webpage module and creates a WebPage object. This WebPage object has empty content and understand DOM.
var system = require('system');
var page = require('webpage').create();
var fs = require('fs');


Then we load up all the necessary JavaScripts files into the page. Before we run any JavaScripts code in the
page, we must first setup the page’s console message handling with onConsoleMessage which we redirect the messages onto our console screen.
page.injectJs("../jquery-1.7.1.min.js") || ( console.log("Unable to load jQuery") && phantom.exit());
page.injectJs("../highcharts/js/highcharts.js") || ( console.log("Unable to load Highcharts") && phantom.exit());
page.injectJs("../highcharts/js/modules/exporting.js") || (console.log("Unable to load Highcharts") && phantom.exit());

page.onConsoleMessage = function (msg) {
console.log(msg);
};


Then we process the command line arguments before we run our export script:
phantom.injectJs(system.args[1]) || (console.log("Unable to load json file") && phantom.exit());

var width = 350, height = 300;
if (system.args.length == 4) {
width = parseInt(system.args[2], 10);
height = parseInt(system.args[3], 10);
}

console.log("Loaded result file");

// Build up result and chart size args for evaluate function
var evalArg = {
result: result,
width: width,
height: height
};


Then we call page.evaluate method, which executes JavaScripts inside the page object. Note that inside the JavaScript code, it is executing
inside the scope of the page. Hence, you cannot access anyPhantomJS modules at all but you can pass data
to the code. In here, we are passing an object with series data into the evaluate’s callback function.
var svg = page.evaluate(function(opt) {
....
}, evalArg);


As we are running with an empty page object, the first thing we need to do is to setup a container in the DOM
for Highcharts to render on. After that, we can construct a Highcharts configuration
object with the series data passing via the callback argument.
var svg = page.evaluate(function(opt) {

// Inject container, so Highcharts can render to
$('body').append('<div id="container"></div>');

var seriesArray = [];
$.each(opt.result.drivers, function(idx, driver) {
seriesArray.push({
name: driver.name,
data: driver.laps,
color: driver.color,
animation: false
});
});

// Normal code to create Highcharts
var chart = new Highcharts.Chart({
chart: {
animation: false,
renderTo: 'container',
width: opt.width,
height: opt.height
},
series: seriesArray,
....
});

return chart.getSVG();
}, evalArg);


Once the chart is created, then we can return the exported SVG content from the evaluate method and save it to a file. As for creating
seriesData.js, since these are all executed on the server side, it is up to the application requirement on
extracting the series data (from a DB or some files) and storing into a JavaScripts file. For instance on PHP, we can simply do
file_put_contents('seriesData.js', "var result = " . json_encode($data) . ";");


According to Torstein Hønsi, the good news is that Highcharts 3.0 will come with a PhantomJS script.
All we need to do is to pass a JavaScripts file with chart configuration in it. This purpose of this article is to show you that you can use Highcharts on
the server side and probably many other tasks.

Here is the full list of the sample program:
var system = require('system');
var page = require('webpage').create();
var fs = require('fs');
page.injectJs("../jquery-1.7.1.min.js") || ( console.log("Unable to load jQuery") && phantom.exit()); page.injectJs("../highcharts/js/highcharts.js") || ( console.log("Unable to load Highcharts") && phantom.exit()); page.injectJs("../highcharts/js/modules/exporting.js") || (console.log("Unable to load Highcharts") && phantom.exit()); page.onConsoleMessage = function (msg) { console.log(msg); };
phantom.injectJs(system.args[1]) || (console.log("Unable to load json file") && phantom.exit()); var width = 350, height = 300; if (system.args.length == 4) { width = parseInt(system.args[2], 10); height = parseInt(system.args[3], 10); } console.log("Loaded result file"); // Build up result and chart size args for evaluate function var evalArg = { result: result, width: width, height: height };
var svg = page.evaluate(function(opt) {

// Inject container, so Highcharts can render to
$('body').append('<div id="container"></div>');

var seriesArray = [];
$.each(opt.result.drivers, function(idx, driver) {
seriesArray.push({
name: driver.name,
data: driver.laps,
color: driver.color,
animation: false
});
});

var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
animations: false,
width: opt.width,
height: opt.height
},
exporting: {
enabled: false,
},
series: seriesArray,
title: {
text: 'Belgian Grand Prix 2012 - Drivers Lap Times'
},
credits: {
text: 'Source: www.f1fanatic.co.uk'
},
yAxis: {
title: {
text: 'Time (secs)'
},
maxPadding: 0.17
},
plotOptions: {
series: {
pointStart: 1
}
},
xAxis: {
title: {
text: 'Laps',
align: 'high'
}
}
});

console.log("Exported to SVG");
return chart.getSVG();
}, evalArg);

fs.isFile("/tmp/chart.svg") && fs.remove("/tmp/chart.svg");
console.log("Saved SVG to file");
fs.write("/tmp/chart.svg", svg);
phantom.exit();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐