There are a number of tools which can easily create PDF files from JSON or raw data provided. But in some situations, we have rich UI elements like images and data representation in graphs, so in that case, we may require PDF as it is.
jsPDF and html2canvas are really powerful tools which can help you to convert the whole HTML page into a multi-page PDF document, which you can show in iFrame or user can even download it.
See a working demo here.
Let’s get started!
Step 1 – First we need to add the jQuery library into our project which is a basic dependency to get this work. Then we need to include the latest jsPDF and Html2Canvas plugins.
<script type="text/javascript" src="lib/jquery.min.js"></script> <script type="text/javascript" src="lib/jspdf.debug.js"></script> <script type="text/javascript" src="lib/html2canvas.js"></script>
Step 2 – As we have a long HTML page to get converted into multiple PDF pages, so will break the whole HTML page into multiple chunks of pages with the help of selectors like we are using page1
, page2
and page3
classes. Each selector or ID will be converted into
Each selector or ID will be converted into the canvas using Html2Canvas
plugin and get pasted into PDF new page using the <strong>jsPDF</strong>
plugin.
Here we have used a single generatePDF()
method having html2canvas called three times to convert three sections of a single HTML page into three pages of PDF file.
html2canvas function will create a canvas and add it as Image in PDF page. Using the addPage()
function we are setting the height and width of the new PDF page. We can adjust it dynamically or as per application requirements.
In the setTimeout()
we have added code to create download link and iFrame if we want to show PDF created in and in page iFrame. Which we will add in the next step.
//Generate PDF
function generatePDF() {
pdf = "";
$("#downloadbtn").hide();
$("#genmsg").show();
html2canvas($(".print-wrap:eq(0)")[0], { allowTaint: true }).then(function(canvas) {
calculatePDF_height_width(".print-wrap",0);
var imgData = canvas.toDataURL("image/png", 1.0);
pdf = new jsPDF('p', 'pt', [PDF_Width, PDF_Height]);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
});
html2canvas($(".print-wrap:eq(1)")[0], { allowTaint: true }).then(function(canvas) {
calculatePDF_height_width(".print-wrap",1);
var imgData = canvas.toDataURL("image/png", 1.0);
pdf.addPage(PDF_Width, PDF_Height);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
});
html2canvas($(".print-wrap:eq(2)")[0], { allowTaint: true }).then(function(canvas) {
calculatePDF_height_width(".print-wrap",2);
var imgData = canvas.toDataURL("image/png", 1.0);
pdf.addPage(PDF_Width, PDF_Height);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
//console.log((page_section.length-1)+"==="+index);
setTimeout(function() {
//Save PDF Doc
pdf.save("HTML-Document.pdf");
//Generate BLOB object
var blob = pdf.output("blob");
//Getting URL of blob object
var blobURL = URL.createObjectURL(blob);
//Showing PDF generated in iFrame element
var iframe = document.getElementById('sample-pdf');
iframe.src = blobURL;
//Setting download link
var downloadLink = document.getElementById('pdf-download-link');
downloadLink.href = blobURL;
$("#sample-pdf").slideDown();
$("#downloadbtn").show();
$("#genmsg").hide();
}, 0);
});
};
We will add a separate function to calculate Heights and Widths of HTML, Canvas and PDF page.
function calculatePDF_height_width(selector,index){
page_section = $(selector).eq(index);
HTML_Width = page_section.width();
HTML_Height = page_section.height();
top_left_margin = 15;
PDF_Width = HTML_Width + (top_left_margin * 2);
PDF_Height = (PDF_Width * 1.2) + (top_left_margin * 2);
canvas_image_width = HTML_Width;
canvas_image_height = HTML_Height;
}
Step 3 - Here we will add HTML content which will be converted into a multipage PDF file.
<!--Generated PDF will load in iFrame when we click on link below-->
<iframe frameBorder="0" id="sample-pdf" style="right:0; top:53px; bottom:0; height:400px; width:100%"></iframe>
<!--Download PDF Link-->
<a id="pdf-download-link" title="Download PDF File">Download PDF file</a>
<!--Create iFrame URL-->
<a id="pdf-showiFrame-link" title="Show PDF in iFrame">Show PDF in iFrame</a>
<div class="print-wrap page1">
<h3>Sample page one for demo</h3>
</div>
<div class="print-wrap page2">
<h3>Sample page two for demo</h3>
</div>
<div class="print-wrap page3">
<h3>Sample page three for demo</h3>
</div>
After combining all sections above our final page will look like below:
<html>
<head>
<title>jsPDF</title>
<script type="text/javascript" src="lib/jquery.min.js"></script>
<script type="text/javascript" src="lib/jspdf.debug.js"></script>
<script type="text/javascript" src="lib/html2canvas.js"></script>
<script>
var pdf,page_section,HTML_Width,HTML_Height,top_left_margin,PDF_Width,PDF_Height,canvas_image_width,canvas_image_height;
function calculatePDF_height_width(selector,index){
page_section = $(selector).eq(index);
HTML_Width = page_section.width();
HTML_Height = page_section.height();
top_left_margin = 15;
PDF_Width = HTML_Width + (top_left_margin * 2);
PDF_Height = (PDF_Width * 1.2) + (top_left_margin * 2);
canvas_image_width = HTML_Width;
canvas_image_height = HTML_Height;
}
//Generate PDF
function generatePDF() {
pdf = "";
$("#downloadbtn").hide();
$("#genmsg").show();
html2canvas($(".print-wrap:eq(0)")[0], { allowTaint: true }).then(function(canvas) {
calculatePDF_height_width(".print-wrap",0);
var imgData = canvas.toDataURL("image/png", 1.0);
pdf = new jsPDF('p', 'pt', [PDF_Width, PDF_Height]);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
});
html2canvas($(".print-wrap:eq(1)")[0], { allowTaint: true }).then(function(canvas) {
calculatePDF_height_width(".print-wrap",1);
var imgData = canvas.toDataURL("image/png", 1.0);
pdf.addPage(PDF_Width, PDF_Height);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
});
html2canvas($(".print-wrap:eq(2)")[0], { allowTaint: true }).then(function(canvas) {
calculatePDF_height_width(".print-wrap",2);
var imgData = canvas.toDataURL("image/png", 1.0);
pdf.addPage(PDF_Width, PDF_Height);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
//console.log((page_section.length-1)+"==="+index);
setTimeout(function() {
//Save PDF Doc
pdf.save("HTML-Document.pdf");
//Generate BLOB object
var blob = pdf.output("blob");
//Getting URL of blob object
var blobURL = URL.createObjectURL(blob);
//Showing PDF generated in iFrame element
var iframe = document.getElementById('sample-pdf');
iframe.src = blobURL;
//Setting download link
var downloadLink = document.getElementById('pdf-download-link');
downloadLink.href = blobURL;
$("#sample-pdf").slideDown();
$("#downloadbtn").show();
$("#genmsg").hide();
}, 0);
});
};
</script>
<style>
.print-wrap {
width: 500px;
}
</style>
</head>
<body>
<iframe frameBorder="0" id="sample-pdf" style="right:0; top:53px; bottom:0; height:400px; width:100%"></iframe>
<a id="pdf-download-link" title="Download PDF File">Download PDF file</a>
<a id="pdf-showiFrame-link" title="Show PDF in iFrame">Show PDF in iFrame</a>
<div class="print-wrap page1">
<h3>Sample page one for demo</h3>
</div>
<div class="print-wrap page2">
<h3>Sample page two for demo</h3>
</div>
<div class="print-wrap page3">
<h3>Sample page three for demo</h3>
</div>
</body>
</html>
That's all folks!!! Let me know in the comments section if you face any issue in plugin this code sample into your app or if you have any suggestion always welcome.
Other Method: Create a Single canvas of the whole HTML section and break it up for different PDF pages.
Keep smiling 🙂
Hi Jolly,
I have question when the div is having more content and it goes to next page, the content should start with top spacing. Can you help me this and also it should have header and footer in all pages
if you try with more than 15 pages, will generate the error: Uncaught (in promise) TypeError: pdf.addPage is not a function
I am still having a problem. I have 5 calls to html2canvas for 5 different divs. Sometimes they fire in the correct order and sometimes they don’t. Sometimes the call to toDataURL finishes in order and sometimes it doesn’t. How do I remedy this? My code fails when it tries to any of the subsequent images before it adds the first one which has the initialization of the PDF or the images show in the incorrect order.
Please disregard my previous comment! I figured out that I messed up adding a new PDF instance instead of a page for pages 2 and up!!
Hi,
.print-wrap {
width: 700px;
margin: auto;
background: #1a577b;
color: #fff;
padding: 15px;
margin-bottom: 30px;
}
when ever i make width 700px or 100% pdf download is not working but when width 500px it workes fine as per demo.Thanks for your great work.Please give me some suggestion how i fix it.
hi i am trying to use the same but with the charts
in my case charts is not getting displayed fully
can you pls say me how can i solved this issuse and where i am doing wrong
I have followed the same procedure but my first page would be blank by this.
Hey, Jayesh please follow demo page code it should work!