4

node.js で Google Chart を読み込もうとしても、何も起こりません。

折れ線グラフ ドキュメントの最初の例を、zombie.js と jsdom の両方で読み込もうとしましたが、どちらの場合もグラフは読み込まれません。

最終的な目標は、生成されたチャートの SVG データを取得して、画像または PDF にエクスポートすることです。したがって、これを実現する別の方法 (node.js または PHP を使用するサーバー側) が可能であれば、私は提案を受け付けています。

:gChartPhpを使用していくつかのチャートの画像を正常に生成しましたが、このプロジェクトの要件では、埋め込みバージョンは現在のAPIによって提供されるインタラクティブバージョンであり、エクスポートバージョンは埋め込みバージョンと視覚的に同一である必要があります(インタラクティブではありません) 、 明らかに)。

編集: PhantomJSにタグを付けました。これが最終的に使用したソリューションであるためです。

リンクがなくて申し訳ありませんが、スパム防止メカニズムにより、2 つしか投稿できません。

4

2 に答える 2

3

私は 8 年遅れていますが、Puppeteer でチャート画像をレンダリングするオープンソース プロジェクトGoogle Charts Nodeをリリースしました (元の PhantomJS ソリューションの後継のようなものです)。

google-charts-nodeは NPM ライブラリとして利用でき、次のように使用できます。

const GoogleChartsNode = require('google-charts-node');

function drawChart() {
  // Set up your chart here, just like in the browser
  // ...

  const chart = new google.visualization.BarChart(container);
  chart.draw(data, options);
}

// Render the chart to image
const image = await GoogleChartsNode.render(drawChart, {
  width: 400,
  height: 300,
});

これで、このimageバッファーをファイルとして保存したり、HTTP 応答などとして返すことができます。

これを作成するのは非常に簡単でした。主な注意事項は次のとおりです。

  1. すべてのチャートが getImageURI をサポートしているわけではないため、これが発生した場合は puppeteer にフォールバックしてスクリーンショットを撮ります。
  2. 遅いです!しかし、要件として Google Charts を使用しなければならない場合、実際には代替手段はありません。この問題は、十分なクラウド コンピューティング リソースで軽減できます。

Github プロジェクトで完全なソースを表示できますが、自分でやりたい場合は、生の操り人形師のフローを次に示します。

async function render() {
  // Puppeteer setup
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // Add the chart
  await page.setContent(`...Insert your Google Charts code here...`);

  // Use getImageURI if available (not all charts support)
  const imageBase64 = await page.evaluate(() => {
    if (!window.chart || typeof window.chart.getImageURI === 'undefined') {
      return null;
    }
    return window.chart.getImageURI();
  });

  let buf;
  if (imageBase64) {
    buf = Buffer.from(imageBase64.slice('data:image/png;base64,'.length), 'base64');
  } else {
    // getImageURI was not available - take a screenshot using puppeteer
    const elt = await page.$('#chart_div');
    buf = await elt.screenshot();
  }

  await browser.close();
  return buf;
}
于 2020-06-24T20:43:02.797 に答える
2

これは理想的なソリューションではありませんでしたが、 PhantomJSで同じ最終目標を達成するために node.js に代わるものを見つけました。チャートを含む HTML ファイル (test.html) を作成し、node.js と同様に、コードを含む JS ファイル (test.js) を作成するだけです。次に、JS ファイルを PhantomJS で実行します。

JS ファイルで、HTML ファイルを Web ページとして開き、レンダリングして、画像バッファーをファイルに保存します。

var page = require('webpage').create();
page.open('test.html', function () {
    page.render('test.png');
    phantom.exit();
});

次に実行します。

phantomjs test.js

グラフを動的に作成するには、次の JS ファイル (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]);
    });
});

次に実行します。

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"}'

外部スクリプトから画像データを取得するには、test2.js (test3.js) のコピーを作成して変更します

page.render('test.png');

console.log(page.renderBase64('png'));

次に、それを呼び出します (たとえば、PHP から):

<?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);

?>

: このプロセス全体を振り返ってみると、node.js で発生していた問題は、チャートが「準備完了」になるまで待機するコールバックまたはタイムアウトを設定していなかった可能性があります。

于 2013-01-04T00:33:06.273 に答える