Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a multi-page pdf from a website using jsPDF and HTML2Canvas?

I have a script that uses HTML2Canvas to take a screenshot of a div within the page, and then converts it to a pdf using jsPDF.

The problem is the pdf that is generated is only one page, and the screenshot requires more than one page in some instances. For example the screenshot is larger than 8.5x11. The width is fine, but I need it to create more than one page to fit the entire screenshot.

Here is my script:

var pdf = new jsPDF('portrait', 'pt', 'letter');
$('.export').click(function() {
      pdf.addHTML($('.profile-expand')[0], function () {
           pdf.save('bfc-schedule.pdf');
      });
 });

Any ideas how I could modify that to allow for multiple pages?

like image 259
Tom Nolan Avatar asked Nov 20 '14 17:11

Tom Nolan


3 Answers

pdf.addHtml does not work if there are svg images on the web page. I copy the solution here, based on the picture being in a canvas already.

Here are the numbers (paper width and height) that I found to work. It still creates a little overlap part between the pages, but good enough for me. if you can find an official number from jsPDF, use them.

var imgData = canvas.toDataURL('image/png');
var imgWidth = 210; 
var pageHeight = 295;  
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm');
var position = 0;

doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;

while (heightLeft >= 0) {
  position = heightLeft - imgHeight;
  doc.addPage();
  doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
  heightLeft -= pageHeight;
}
doc.save( 'file.pdf');`
like image 190
Trilok Nagvenkar Avatar answered Oct 31 '22 14:10

Trilok Nagvenkar


you can use page split option of addhtml like this:

var options = {
    background: '#fff',
    pagesplit: true
};

var doc = new jsPDF(orientation, 'mm', pagelayout);
doc.addHTML(source, 0, 0, options, function () {
        doc.save(filename + ".pdf");
        HideLoader();`enter code here`
});

Note: This will break the html on multiple pages but these pages will get stretched. Stretching is a issue in addhtml till now and i am still not able to find on internet how to solve this issue.

like image 5
Ajay Gunpal Avatar answered Oct 31 '22 15:10

Ajay Gunpal


I was able to get it done using async functionality.

(async function loop() {
    var pages = [...]
    for (var i = 0; i < pages.length; i++) {
      await new Promise(function(resolve) {
        html2canvas(pages[i], {scale: 1}).then(function(canvas) {

          var img=canvas.toDataURL("image/png");
          doc.addImage(img,'JPEG', 10, 10);
          if ((i+1) == pages.length) {
            doc.save('menu.pdf');
          } else {
            doc.addPage();
          }
          resolve();
        });
      });
    }
})();
like image 1
avoliva Avatar answered Oct 31 '22 14:10

avoliva