Hayden
Hayden

Reputation: 51

How to add top margin when using html2canvas and jspdf, when the canvas is split on multiple pages?

I'm using HTML2Canvas and jsPDF to create a pdf of a dynamic webpage, when the size of the canvas is great than one page I add another page and re-add the image shifting it up to the next page. Everything is working well however I can not figure out how to set the top margin and as a result the 2nd page onward all the content is on the very top of the page. Is there a way to set the top margin for all pages?

            html2canvas($("#formpdfarea"), {
            onrendered: function(canvas) {
                var imgData = canvas.toDataURL(
                    'image/png');     
                var doc = new jsPDF('l', 'mm', 'letter');
                doc.addImage(imgData, 'PNG', 5, 0);

                //output is 96dpi, additional pages added if output is greater than 816 pixels (816p/96dpi = 8.5 inches)
                if(canvas.height > 816){ 
                    for(i=1; i*816<canvas.height; i++){
                        doc.addPage();
                        //-215.89mm which is -8.5inches
                        doc.addImage(imgData, 'PNG',5,-215.89*i);
                    }
                }
                doc.save('formoutput.pdf');
            }
        });

Upvotes: 5

Views: 12589

Answers (2)

Razi Syed
Razi Syed

Reputation: 289

I resolved this by adjusting the mediaBox properties.

The method putPages in jspdf writes out a page, and you can manipulate the media box and page width/height to adjust the page margins. I hardcoded additional 52 (0.75in) to height and -36 (0.5in) to mediabox to give every page a margin.

This is the code change:

wPt = (pageWidth = pagedim[n].width) * k;
hPt = (pageHeight = pagedim[n].height + 52) * k;
out('<</Type /Page');
out('/Parent 1 0 R');
out('/Resources 2 0 R');
out('/MediaBox [-36 0 ' + f2(wPt) + ' ' + f2(hPt) + ']');

You would also have to change the page size so that the footer looks right also.

I used:

canvas.height = 72 * 10.25; // instead of 11
canvas.width = 72 * 8.5; 

This can be turned in to a proper feature instead of hardcoding it, but works for now.

Upvotes: 1

Andrew Rockwell
Andrew Rockwell

Reputation: 454

I spent multiple hours looking for a solution residing in jsPDF's library but it seems none are available at this time. Once you specify pagesplit it seems to ignore the other jsPDF options like margin.

SO, I did it myself, breaking the pages up manually. It's actually relatively simple. :)

I created this for a large table. If you're trying to break up something other than a table you can still use this concept. All you'd really need to do is change up the CSS classes to make different parts visible.

function add_page() {
    // Youre header & footer stuff goes here
    pdf.addHTML($('#pdfPage'), 20, 26, options, function() {
        check_page();
    });
}
function check_page() {
    tr_rows = tr_rows - 28;
    if( tr_rows > 0 ) {
        $('#pdfPage').removeClass('pdf_page_' + current_pdf_page).addClass('pdf_page_' + ++current_pdf_page);
        pdf.addPage();
        add_page();
    } else {
        pdf.save( filename + '.pdf' );
    }
}
$('#pdfPage').addClass('pdf_page_1');
tr_rows = $('#pdfPage tbody tr').length;
current_pdf_page = 1;
add_page();

And here are my CSS classes:

.pdf_page_1 tr:nth-child(n+28) { display: none; }

.pdf_page_2 tr:nth-child(-n+28) { display: none; }
.pdf_page_2 tr:nth-child(n+56) { display: none; }

.pdf_page_3 tr:nth-child(-n+56) { display: none; }
.pdf_page_3 tr:nth-child(n+84) { display: none; }

.pdf_page_4 tr:nth-child(-n+84) { display: none; }
.pdf_page_4 tr:nth-child(n+112) { display: none; }

#pdfPage tr:first-child { display: table-row !important; }

Upvotes: 0

Related Questions