将Google Chart转换为PNG Image&下载

时间:2015-06-28 09:51:57

标签: php image charts google-visualization

问题
1.如何获取图表图像并将其传递到另一页面。 (PHP)
2.添加" google.visualization.events.addListener"后,目前无法显示折线图。方法。
(资源:https://developers.google.com/chart/interactive/docs/printing

当前代码:

<html>
<head>
  <script type="text/javascript" src="https://www.google.com/jsapi"></script>
  <script type="text/javascript">
    google.load('visualization', '1.1', {packages: ['line']});
    google.setOnLoadCallback(drawChart);

    function drawChart() {

      var data = new google.visualization.DataTable();
      data.addColumn('number', 'Day');
      data.addColumn('number', 'Guardians of the Galaxy');
      data.addColumn('number', 'The Avengers');
      data.addColumn('number', 'Transformers: Age of Extinction');

      data.addRows([
        [1,  37.8, 80.8, 41.8],
        [2,  30.9, 69.5, 32.4],
        [3,  25.4,   57, 25.7],
        [4,  11.7, 18.8, 10.5],
        [5,  11.9, 17.6, 10.4],
        [6,   8.8, 13.6,  7.7],
        [7,   7.6, 12.3,  9.6],
        [8,  12.3, 29.2, 10.6]
      ]);

      var options = {
        chart: {
          title: 'Box Office Earnings in First Two Weeks of Opening',
          subtitle: 'in millions of dollars (USD)'
        },
        width: 900,
        height: 500
      };

//      var chart = new google.charts.Line(document.getElementById('linechart_material'));
var linechart_material = document.getElementById('linechart_material');
 var chart = new google.charts.Line(document.getElementById('linechart_material'));

// Wait for the chart to finish drawing before calling the getImageURI() method.
    google.visualization.events.addListener(my_chart, 'ready', function () {
      linechart_material.innerHTML = '<img src="' + chart.getImageURI() + '">';
      <?php $img //Get the chart.getImageURI() ?>
    });

      chart.draw(data, options);
    }
  </script>
</head>
<body>
  <div id="linechart_material"></div>


<form method="post" action="doInsert.php" enctype="multipart/form-data">
    <input type='hidden' name="imageName" value='<?php echo $img ; ?>' />
 <div class="txtCenter"><input type="submit" value="Save the Report"  style="width:300px; font-weight: bold;"></div>
</form>
</body>
</html>

我也参考了这个资源 https://gist.github.com/battlehorse/1333906 但是,此资源无法显示图像,当我下载图像时格式错误。

<html>
  <head>
    <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script> 
    <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script>
    <script>
      function getImgData(chartContainer) {
      //  var chartArea = chartContainer.getElementsByTagName('iframe')[0].
        //  contentDocument.getElementById('chartArea');
        var chartArea = chartContainer.getElementsByTagName('div')[1];

        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 imgData = canvas.toDataURL("image/png");
        canvas.parentNode.removeChild(canvas);
        return imgData;
      }

      function saveAsImg(chartContainer) {
        var imgData = getImgData(chartContainer);

        // Replacing the mime-type will force the browser to trigger a download
        // rather than displaying the image in the browser window.
        window.location = imgData.replace("image/png", "image/octet-stream");
      }


//Conver Image
      function toImg(chartContainer, imgContainer) { 
        var doc = chartContainer.ownerDocument;
        var img = doc.createElement('img');
        img.src = getImgData(chartContainer);

        while (imgContainer.firstChild) {
          imgContainer.removeChild(imgContainer.firstChild);
        }
        imgContainer.appendChild(img);
      }
    </script>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart", "treemap", "geochart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {

        // Line chart
        data = new google.visualization.DataTable();
        data.addColumn('string', 'Year');
        data.addColumn('number', 'Sales');
        data.addColumn('number', 'Expenses');
        data.addRows(4);
        data.setValue(0, 0, '2004');
        data.setValue(0, 1, 1000);
        data.setValue(0, 2, 400);
        data.setValue(1, 0, '2005');
        data.setValue(1, 1, 1170);
        data.setValue(1, 2, 460);
        data.setValue(2, 0, '2006');
        data.setValue(2, 1, 860);
        data.setValue(2, 2, 580);
        data.setValue(3, 0, '2007');
        data.setValue(3, 1, 1030);
        data.setValue(3, 2, 540);

        var chart = new google.visualization.LineChart(document.getElementById('line_div'));
        chart.draw(data, {width: 450, height: 300, title: 'Company Performance'});


      }
    </script>
  </head>
  <body>
    <div id="img_div" style="position: fixed; top: 0; right: 0; z-index: 10; border: 1px solid #b9b9b9">
      Image will be placed here
    </div>


    <button onclick="saveAsImg(document.getElementById('line_div'));">Save as PNG Image</button>
    <button onclick="toImg(document.getElementById('line_div'), document.getElementById('img_div'));">Convert to image</button>
    <div id="line_div"></div>

</body>
</html>

1 个答案:

答案 0 :(得分:0)

当我将图表图像添加到PDF文件时,我遇到了同样的问题。我最终做了什么:

我像往常一样准备HTML + Javascript图表并将其写入临时目录中的HTML文件。然后我使用PhantomJS(http://phantomjs.org/)创建页面的屏幕截图,然后我可以在任何地方使用。

最棒的是:它适用于任何本地HTML页面。如果您只有一个URL,请使用file_get_contents()或cURL检索其内容并首先将其写入本地HTML文件。

胆量:

启动,下载phantomjs.exe并将其解压缩到应用程序可以访问的目录。我的示例使用的是我在应用程序根目录中复制到lib / phantomjs的1.9.8版。

我有一个函数接受HTML文件路径作为参数和一组PhantomJS选项。我建议将它添加到辅助类中。

function getHTMLImage($page, $options = array(), $js = null) {
    // Prepare the PhantomJS directory that contains phantomjs.exe, e.g. lib or vendor
    $phantomDir = $_SERVER['DOCUMENT_ROOT'] . '/lib/phantomjs/';
    // Add the PhantomJS directory to the PATH
    $origPath = str_replace('"', '', getenv('PATH'));
    if (!in_array($phantomDir, explode('/', $origPath)))
          putenv('PATH=' . $origPath . '/' . $phantomDir);

    // PhantomJS requires a Javascript file to process the request. In case no Javascript processing file is given, use the default
    if (is_null($js)) $js = $phantomDir . 'phantom.js';

    // Prepare the PhantomJS call
    $exec = 'phantomjs --ignore-ssl-errors=yes ' . $js . ' ' . escapeshellarg($page);
    // Prepare the PhantomJS options, e.g. width and height
    foreach ($options as $option) {
        $exec .= ' ' . escapeshellarg($option);
    }

    // Call PhantomJS. To catch errors, call exec($exec . ' 2>&1', $output, $errorMsg);
    exec($exec, $output);

    // Decode and return the image data
    return ($output ? base64_decode(reset($output)) : false);
}

Javascript文件(我的名为phantom.js,与phantomjs.exe放在同一目录中):

args = require('system').args;
page = require('webpage').create();

// In this case, I expect these indexes to be the width and height of the chart
if (typeof args[2] !== undefined) {
    page.viewportSize = {
        width: args[2],
        height: (typeof args[3] === undefined ? args[2] : args[3])
    };
}

page.open(args[1], function() {
    var base64 = page.renderBase64('png');
    console.log(base64);
    phantom.exit();
});

这样称呼:

// Make sure $width and $height are set, or exclude them altogether
$output = getHTMLImage($htmlPath, array($width, $height));
// Example output, instead you want to save the image and send its file name to the next PHP file
header('Content-Type: image/png');
exit($output);

我建议将图像文件名传递给下一个PHP文件,然后从您保存图像的位置检索图像(例如文档根目录中的/ temp)。

事件监听器不一定是必要的。另外,您无法以您提出的方式从Javascript到PHP获取图像URI - 您需要进行AJAX调用或表单发布。

此外,使用1.0图表包更好 - 特别是在生产环境中:

google.load('visualization', **'1'**, {packages: ['line']});

1.1是候选版本,可能包含错误并导致不兼容。