Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate single-page .pdf with PhantomJS

I'm exporting a webpage of variable height into pdf using PhantomJS. Since pdfs can have any page size (more like ratio though, since it's vectorial), I would like to export it in a way that creates a single page in the pdf in which to fit the entire webpage.

Luckily, using the evaluate PhantomJS method I can easily detect the page height

page.includeJs('jquery.js', function() {
  var pageHeight = page.evaluate(function() {
    return $('#content').height();
  });
});

However, I'm not sure how I can use that to my advantage. viewportSize doesn't seem to affect this in any way, since I'm not rendering the viewport but the entire document. I set it to a fixed {width: 800, height: 800}

So I can't wrap my head around the paperSize sizes. Setting the height to the returned pageHeight will render 1.5x pages, so I tried tweaking the width but it doesn't really add up to any formula that I can understand.

Any ideas in how to achieve this, or do you have more insights into the correlation between the paperSize property and the pixel-sized bounds rendered from the page

like image 460
treznik Avatar asked Aug 24 '13 08:08

treznik


2 Answers

Extending Cybermaxs' Answer, I added

  • set a fixed width (36cm corresponded well with my view port) and
  • a unit to the height calculation
  • set the margin to 0px.

I can't give a good explanation, but it works for me.

The full script:

var page = require('webpage').create(),
system = require('system'),
address, output, size;

if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: screenshot.js <URL> <filename>');
    phantom.exit(1);
} else {
    address = system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 1280, height: 900};
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
            phantom.exit();
        } else {
            window.setTimeout(function () {
                page.includeJs("//code.jquery.com/jquery-1.10.1.min.js", function() {
                    var size = page.evaluate(function () {
                        return {width: width = "36cm", height : $(document).height()*2+400 + "px", margin: '0px' };
                    });
                    page.paperSize = size;          
                    page.render(output);
                    phantom.exit();
                });
            }, 400);
        }
    });
}
like image 170
Max Avatar answered Nov 13 '22 02:11

Max


viewportSize simulates the size of the window like in a traditional browser. It affects the rendering of the page because of HTML layout but not directly pdf rendering.

Use page.papersize to define the size of the web page when rendered as a PDF. With a bit of Jquery, it's easy to render the web page in a single document, like this :

var page = require('webpage').create(),
    system = require('system'),
    address, output;

if (system.args.length != 3) {
    console.log('Usage: spdf.js URL filename');
    phantom.exit(1);
} else {
    address = system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 600, height: 600 };

    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
            phantom.exit();
        } else {
            var size = page.evaluate(function () {
                return {width: width = $(document).width(), height : $(document).height() };
            });

            page.paperSize = size;

            page.render(output);
            phantom.exit();
        }
    });
}
like image 44
Cybermaxs Avatar answered Nov 13 '22 00:11

Cybermaxs