Embedding charts in the PDF using TCPDF library

4.2k views Asked by At

I am working on a project in which a PDF file is to be generated. I have used Google Chart API for generating different charts. I am using the TCPDF library for converting them into PDF but I am unable to embed these genearted graphs into the PDFs. I think TCPDF does not accept the contents written in the script tag. How can I overcome this problem?

1

There are 1 answers

10
RuubW On

I ran into the same problem except I was using FPDF. At the end of the day, a PDF file contains static content, so Javascript is out of the question unfortunately. What I ended up doing:

I prepare the chart HTML + Javascript like always and write it to a HTML file in my temp directory. Then I use PhantomJS (http://phantomjs.org/) to create a screenshot of the page which I then include in my PDF (or anywhere, really).

The great thing: it works with ANY local HTML page. If you only have a URL, use file_get_contents() or cURL to retrieve its contents and write it to a local HTML file first.

The guts:

To start, download and extract phantomjs.exe to a directory your application can access. My example uses version 1.9.8 that I copied to lib/phantomjs in my application root.

I have a function that accepts a HTML file path as parameter and a set of PhantomJS options. I suggest adding it to a helper class.

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

The Javascript file (mine is called phantom.js and is placed in the same directory as 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();
});

Call it like this:

// Make sure $width and $height are set, or exclude them altogether
$output = getHTMLImage($htmlPath, array($width, $height));
// Example output, you want to save the image and include it in your PDF file
header('Content-Type: image/png');
exit($output);