Have you ever wondered how client-side PDFs are produced?
Have you tried a few alternatives and realized that there is nothing substantial you can do? I've also used many libraries in various projects but have yet to find a better option. So, if you ever run into a problem in the future, keep in mind that each solution or package works differently, and you must pick what you require.
In this article, I'll discuss how I used 'html2Canvas and jsPdf,' as well as the challenges I encountered and what I discovered after a lengthy examination, as well as taking a few PDFs and comparing them to various alternatives available online.
My current problem statement begins with one of the environments in which my PDF was producing partial images. After a lot of digging, I assumed it was a issue with package versions, but it didn't work, so if you ever run into this problem, try * a fresh installation of node and/or npm * first.
When your pdf image appears stretched but your UI looks great as intended, you've got a serious problem.
As you might expect, I started by fitting to a specific dimension.
Did it work? No.
Please accept my apologies if I have not answered to you yet. Hold on a little longer, and you'll see what I'm talking about.
In this post, we'll look at how to use Html2Canvas and JsPdf in a React project. There are a few alternative options out there, such as integrating with HTML directly.
Hear are the list of solutions you can try as per your sutiation.
You may have came across the solutions given below, and if they did not work, scroll down to the bottom where I'll explain how you might reach a better, if not precise, result.
1. How to set image to fit to width of the page using jsPDF?
var doc = new jsPDF("p", "mm", "a4");
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
2. get width 100% of PDF file and auto height
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: 'landscape',
});
const imgProps= pdf.getImageProperties(imgData);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
pdf.save('download.pdf');
});
3. fit a web page into the pdf document, without losing the aspect ratio.
var divHeight = $('#div_id').height();
var divWidth = $('#div_id').width();
var ratio = divHeight / divWidth;
html2canvas(document.getElementById("div_id"), {
height: divHeight,
width: divWidth,
onrendered: function(canvas) {
var image = canvas.toDataURL("image/jpeg");
var doc = new jsPDF(); // using defaults: orientation=portrait, unit=mm, size=A4
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
height = ratio * width;
doc.addImage(image, 'JPEG', 0, 0, width-20, height-10);
doc.save('myPage.pdf'); //Download the rendered PDF.
}
});
4. dynamic sized image
let width = doc.internal.pageSize.getWidth()
let height = doc.internal.pageSize.getHeight()
let widthRatio = width / canvas.width
let heightRatio = height / canvas.height
let ratio = widthRatio > heightRatio ? heightRatio : widthRatio
doc.addImage(
canvas.toDataURL('image/jpeg', 1.0),
'JPEG',
0,
0,
canvas.width * ratio,
canvas.height * ratio,
)
5. Solution for all screen sizes and dynamic orientation:
html2canvas(Component).then((canvas) => {
const componentWidth = Component.offsetWidth
const componentHeight = Component.offsetHeight
const orientation = componentWidth >= componentHeight ? 'l' : 'p'
const imgData = canvas.toDataURL('image/png')
const pdf = new jsPDF({
orientation,
unit: 'px'
})
pdf.internal.pageSize.width = componentWidth
pdf.internal.pageSize.height = componentHeight
pdf.addImage(imgData, 'PNG', 0, 0, componentWidth, componentHeight)
pdf.save('download.pdf')
})
6. doc width/height
var myCanvas = document.getElementById("exportToPDF");
html2canvas(myCanvas, {
onrendered: function(canvas) {
var imgData = canvas.toDataURL(
'image/jpeg', 1.0);
//Get the original size of canvas/image
var img_w = canvas.width;
var img_h = canvas.height;
//Convert to mm
var doc_w = ExportModule.pxTomm(img_w);
var doc_h = ExportModule.pxTomm(img_h);
//Set doc size
var doc = new jsPDF('l', 'mm', [doc_w, doc_h]);
//set image height similar to doc size
doc.addImage(imgData, 'JPG', 0, 0, doc_w, doc_h);
var currentTime = new Date();
doc.save('Dashboard_' + currentTime + '.pdf');
}
});
7. calculate aspect ratio dynamicaly
So, if you've read thus far and still haven't found the best solution, don't despair; there is no better solution. Everyone has a different problem, and we all have different solutions. My solution is as follows:
const domElement = document.getElementById("divToPrint");
const width = domElement.clientWidth;
const height = domElement.clientHeight;
will assist in the collection and generation of images specific to the client device, as well as the use of scall to produce a better image
html2canvas(domElement,
{
scale: width / height
}).then(function (canvas) {
const img = canvas.toDataURL("image/png", 2.0);
const pdf = new jsPdf("l", "mm", [297, 210]);
pdf.addImage(img, "png", 10, 10, 260, 160, "alias", "FAST");
pdf.save(name);
});
If you'd like to add more information to the pdf, that's an added benefit. you can use opions as shown below.
pdf.setDisplayMode("fullpage");
pdf.setProperties({
title: name,
subject: "subject"
});
pdf.setDisplayMode("fullpage");
Conclusion
In this article we witnessed in this article we looked into how to set a width on an image. We also looked into how we can dynamically set the pdf orientation and a size as well. If you're looking forword to see different options that are available in the jspdf comment below and I'll make an article demonstrating all the options.
resources
JsPdf
Top comments (2)
I have not, will give it a Try once thanks for the suggestion.
have you tried pdfmake?