最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Server-Side HighStock charts generation with NodeJS - Stack Overflow

programmeradmin3浏览0评论

I'm using HighStock to generate some charts in browser. But now I want to store some of them at the server. So I know that HighCharts can be exported to the server but I'd rather use some other way if possible. The thing is to run HighStock at the server and convert the svg to some image format and then store it there.

Quick googling gives me this page. Combining HighCharts and NodeJS seems to be the right way but this solution does not work for newer versions of HighCharts. More precisely, using jsdom module (v0.2.10 - the latest) in NodeJS with HighStock v1.0.2 (look at the following code):

var jsdom = require('jsdom');
var fs = require('fs');
var jQuery = fs.readFileSync('./js/jquery-1.7.min.js').toString();
var Highstock = fs.readFileSync('./js/highstock.js').toString();
jsdom.env({
    html: '<div id="container"></div>',
    src: [ jQuery, Highstock ],
    done: function(errors, window) {
        if (errors) return console.log(errors);
        var Highcharts = window.Highcharts;
        var chart = new Highcharts.Chart(options);
    }
});

throws an exception:

Error: Invalid character: Invalid character in tag name: <

Somehow these two libraries does not seem to work together. So this may work with older versions of HighStock but actually I need HighStock v1.0.2.

Is there any solution for this problem? Some better library that jsdom? Or some strange yet working tricks? Any idea appreciated. :)

// EDIT

Thanks to ReCoder I've managed to get it working. Main thing was to add forExport flag to the options (preventing exceptions). Unfortunetly this generated the chart but did not update the holder. I've managed to get it working after adding exporting module (part of HighStock package). The full working code looks like this:

var jsdom = require('jsdom');
var fs = require('fs');
var jQuery = fs.readFileSync('./js/jquery-1.7.min.js').toString();
var Highstock = fs.readFileSync('./js/highstock.src.js').toString();
var Exporting = fs.readFileSync('./js/exporting.src.js').toString();

jsdom.env({
    html: '<div id="container"></div>',
    src: [ jQuery, Highstock, Exporting ],
    done: function(errors, window) {
        if (errors) return console.log(errors);
        var Highcharts = window.Highcharts;
        var chart = new Highcharts.Chart({
              chart: {
                 renderTo: 'container',
                 animation: false,
                 forExport: true       
              },
              exporting: { enabled: false },
              xAxis: {
                 categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
              },
              series: [{
                 animation: false,
                 name: 'Tokyo',
                 data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
              }, {
                 animation: false,      
                 name: 'New York',
                 data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
              }, {
                 animation: false,      
                 name: 'Berlin',
                 data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
              }, {
                 animation: false,      
                 name: 'London',
                 data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
              }]
        });

        var svg = chart.getSVG();

        fs.writeFile("./test.svg", svg, function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log("The file was saved!");
            }            
        }); 
    }
});

The chart is not as good as it should be (for example labels badly placed), but maybe it's a matter of tuning options. At least it works!

I'm using HighStock to generate some charts in browser. But now I want to store some of them at the server. So I know that HighCharts can be exported to the server but I'd rather use some other way if possible. The thing is to run HighStock at the server and convert the svg to some image format and then store it there.

Quick googling gives me this page. Combining HighCharts and NodeJS seems to be the right way but this solution does not work for newer versions of HighCharts. More precisely, using jsdom module (v0.2.10 - the latest) in NodeJS with HighStock v1.0.2 (look at the following code):

var jsdom = require('jsdom');
var fs = require('fs');
var jQuery = fs.readFileSync('./js/jquery-1.7.min.js').toString();
var Highstock = fs.readFileSync('./js/highstock.js').toString();
jsdom.env({
    html: '<div id="container"></div>',
    src: [ jQuery, Highstock ],
    done: function(errors, window) {
        if (errors) return console.log(errors);
        var Highcharts = window.Highcharts;
        var chart = new Highcharts.Chart(options);
    }
});

throws an exception:

Error: Invalid character: Invalid character in tag name: <

Somehow these two libraries does not seem to work together. So this may work with older versions of HighStock but actually I need HighStock v1.0.2.

Is there any solution for this problem? Some better library that jsdom? Or some strange yet working tricks? Any idea appreciated. :)

// EDIT

Thanks to ReCoder I've managed to get it working. Main thing was to add forExport flag to the options (preventing exceptions). Unfortunetly this generated the chart but did not update the holder. I've managed to get it working after adding exporting module (part of HighStock package). The full working code looks like this:

var jsdom = require('jsdom');
var fs = require('fs');
var jQuery = fs.readFileSync('./js/jquery-1.7.min.js').toString();
var Highstock = fs.readFileSync('./js/highstock.src.js').toString();
var Exporting = fs.readFileSync('./js/exporting.src.js').toString();

jsdom.env({
    html: '<div id="container"></div>',
    src: [ jQuery, Highstock, Exporting ],
    done: function(errors, window) {
        if (errors) return console.log(errors);
        var Highcharts = window.Highcharts;
        var chart = new Highcharts.Chart({
              chart: {
                 renderTo: 'container',
                 animation: false,
                 forExport: true       
              },
              exporting: { enabled: false },
              xAxis: {
                 categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
              },
              series: [{
                 animation: false,
                 name: 'Tokyo',
                 data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
              }, {
                 animation: false,      
                 name: 'New York',
                 data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
              }, {
                 animation: false,      
                 name: 'Berlin',
                 data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
              }, {
                 animation: false,      
                 name: 'London',
                 data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
              }]
        });

        var svg = chart.getSVG();

        fs.writeFile("./test.svg", svg, function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log("The file was saved!");
            }            
        }); 
    }
});

The chart is not as good as it should be (for example labels badly placed), but maybe it's a matter of tuning options. At least it works!

Share Improve this question edited Mar 20, 2012 at 10:15 freakish asked Feb 20, 2012 at 14:24 freakishfreakish 56.6k12 gold badges139 silver badges177 bronze badges 3
  • interested in your project, is there a site for it? – bouncingHippo Commented Nov 13, 2012 at 15:59
  • if i don't intend to store things to the server, do i still need to use nodeJS? I just want the web site to get data straight from Yahoo Finance and plot it using HighStocks/HighCharts – bouncingHippo Commented Nov 14, 2012 at 20:09
  • @bouncingHippo No, you don't need to use NodeJS. And that's not really a project, I've been just testing server-side image generation. Unfortunetly it was not working as I expected it to work, so I've abandoned it. – freakish Commented Nov 14, 2012 at 21:52
Add a ment  | 

3 Answers 3

Reset to default 2

That can be fixed by raising the "forExport" flag in options object:

options.chart.forExport = true;

I tried to recreate your example and I get jQuery and Highcharts loaded with jsdom. It looks like Highcharts tries to call createElement with an html fragment:

createElement('<div filled="f" stroked="f" style="position: absolute;left:0;top:0;width:10px;height:10px;"/>')

This looks fishy. I'm not sure how it works in the browser - I can't call createElement with that in my browser either (Chromium).

I replaced node.js with phantomJs which did a good job, as described in Generating HTML Canvas image data server-side? (example is from jQplot, but works for highchart as well.)

发布评论

评论列表(0)

  1. 暂无评论