How to set image to fit width of the page using jsPDF?
JavascriptJspdfJavascript Problem Overview
Is there any way to solve this? I tried to set width and height in mm. How can I set it to full-width?
Javascript Solutions
Solution 1 - Javascript
You can get the width and height of PDF document like below,
var doc = new jsPDF("p", "mm", "a4");
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
Then you can use this width and height for your image to fit the entire PDF document.
var imgData = 'data:image/jpeg;base64,/9j/4AAQSkZJ......';
doc.addImage(imgData, 'JPEG', 0, 0, width, height);
Make sure that your image has the same size (resolution) of the PDF document. Otherwise it will look distorted (stretched).
If you want convert px
to mm
use this link http://www.endmemo.com/sconvert/millimeterpixel.php
Solution 2 - Javascript
If you need to get width 100% of PDF file and auto height you can use getImageProperties
property of html2canvas library
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');
});
Solution 3 - Javascript
My answer deals with a more specific case of what you are asking but I think one could draw some ideas from this to apply more generally. Also, I would post this as a comment to Purushoth's answer (on which mine is based), if only I could.
Ok, so my problem was how to fit a web page into the pdf document, without losing the aspect ratio. I used jsPDF in conjuction with html2canvas and I calculated the ratio from my div
's width and height. I applied that same ratio to the pdf document and the page fit perfectly onto the page without any distortion.
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.
}
});
Solution 4 - Javascript
I discovered this while experimenting with html2canvas this morning. While this doesn't include provisions for printing multiple pages it does scale the image to page width and reframes the height in ratio to the adjusted width:
html2canvas(document.getElementById('testdiv')).then(function(canvas){
var wid: number
var hgt: number
var img = canvas.toDataURL("image/png", wid = canvas.width, hgt = canvas.height);
var hratio = hgt/wid
var doc = new jsPDF('p','pt','a4');
var width = doc.internal.pageSize.width;
var height = width * hratio
doc.addImage(img,'JPEG',20,20, width, height);
doc.save('Test.pdf');
});
Solution 5 - Javascript
The API changed since this commit, using version 1.4.1 it's now
var width = pdf.internal.pageSize.getWidth();
var height = pdf.internal.pageSize.getHeight();
Solution 6 - Javascript
If you want a dynamic sized image to automatically fill the page as much as possible and still keep the image width/height-ratio, you could do as follows:
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,
)
Solution 7 - Javascript
It's easy to fit the page if you only have one image. The more challenge task is to fit images with various sizes to a pdf file. The key to archive that is to calculate the aspect ratio of the image and relative width/height ratio of the page. The following code is what I used to convert multiple images online to a PDF file. It will rotate the image(s) based on the orientation of the images/page and set proper margin. My project use images with online src. You should be able to modify to suit your needs.
As for image rotation, if you see a blank page after rotation, it could simply be that the image is out of bounds. See this answer for details.
function exportPdf(urls) {
let pdf = new jsPDF('l', 'mm', 'a4');
const pageWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
const pageRatio = pageWidth / pageHeight;
for (let i = 0; i < urls.length; i++) {
let img = new Image();
img.src = urls[i];
img.onload = function () {
const imgWidth = this.width;
const imgHeight = this.height;
const imgRatio = imgWidth / imgHeight;
if (i > 0) { pdf.addPage(); }
pdf.setPage(i + 1);
if (imgRatio >= 1) {
const wc = imgWidth / pageWidth;
if (imgRatio >= pageRatio) {
pdf.addImage(img, 'JPEG', 0, (pageHeight - imgHeight / wc) / 2, pageWidth, imgHeight / wc, null, 'NONE');
}
else {
const pi = pageRatio / imgRatio;
pdf.addImage(img, 'JPEG', (pageWidth - pageWidth / pi) / 2, 0, pageWidth / pi, (imgHeight / pi) / wc, null, 'NONE');
}
}
else {
const wc = imgWidth / pageHeight;
if (1 / imgRatio > pageRatio) {
const ip = (1 / imgRatio) / pageRatio;
const margin = (pageHeight - ((imgHeight / ip) / wc)) / 4;
pdf.addImage(img, 'JPEG', (pageWidth - (imgHeight / ip) / wc) / 2, -(((imgHeight / ip) / wc) + margin), pageHeight / ip, (imgHeight / ip) / wc, null, 'NONE', -90);
}
else {
pdf.addImage(img, 'JPEG', (pageWidth - imgHeight / wc) / 2, -(imgHeight / wc), pageHeight, imgHeight / wc, null, 'NONE', -90);
}
}
if (i == urls.length - 1) {
pdf.save('Photo.pdf');
}
}
}
}
> If this is a bit hard to follow, you can also use .addPage([imgWidth, imgHeight])
, which is more straightforward. The downside of this method is that the first page is fixed by new jsPDF()
. See this answer for details.
Solution 8 - Javascript
Solution for all screen sizes and dynamic orientation:
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
export default async function downloadComponentInPDF(Component: HTMLElement) {
await 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')
})
}
Solution 9 - Javascript
A better solution is to set the doc width/height using the aspect ratio of your image.
var ExportModule = {
// Member method to convert pixels to mm.
pxTomm: function(px) {
return Math.floor(px / $('#my_mm').height());
},
ExportToPDF: function() {
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');
}
});
},
}
<script src="Scripts/html2canvas.js"></script>
<script src="Scripts/jsPDF/jsPDF.js"></script>
<script src="Scripts/jsPDF/plugins/canvas.js"></script>
<script src="Scripts/jsPDF/plugins/addimage.js"></script>
<script src="Scripts/jsPDF/plugins/fileSaver.js"></script>
<div id="my_mm" style="height: 1mm; display: none"></div>
<div id="exportToPDF">
Your html here.
</div>
<button id="export_btn" onclick="ExportModule.ExportToPDF();">Export</button>
Solution 10 - Javascript
i faced same problem but i solve using this code
html2canvas(body,{
onrendered:function(canvas){
var pdf=new jsPDF("p", "mm", "a4");
var width = pdf.internal.pageSize.getWidth();
var height = pdf.internal.pageSize.getHeight();
pdf.addImage(canvas, 'JPEG', 0, 0,width,height);
pdf.save('test11.pdf');
}
})
Solution 11 - Javascript
This is how I've achieved in Reactjs.
Main problem were ratio and scale If you do a quick window.devicePixelRatio, it's default value is 2 which was causing the half image issue.
const printDocument = () => {
const input = document.getElementById('divToPrint');
const divHeight = input.clientHeight
const divWidth = input.clientWidth
const ratio = divHeight / divWidth;
html2canvas(input, { scale: '1' }).then((canvas) => {
const imgData = canvas.toDataURL('image/jpeg');
const pdfDOC = new JSPDF("l", "mm", "a0"); // use a4 for smaller page
const width = pdfDOC.internal.pageSize.getWidth();
let height = pdfDOC.internal.pageSize.getHeight();
height = ratio * width;
pdfDOC.addImage(imgData, 'JPEG', 0, 0, width - 20, height - 10);
pdfDOC.save('summary.pdf'); //Download the rendered PDF.
})
}
Solution 12 - Javascript
my solution is to check what ratio (height or width) need to apply depending of the pdf orientation and image size. note: set margin to 0 if no margin is required.
const imgData = canvas.toDataURL("image/jpeg");
const pdf = new jsPDF({
orientation: "portrait", // landscape or portrait
unit: "mm",
format: "a4",
});
const imgProps = pdf.getImageProperties(imgData);
const margin = 0.1;
const pdfWidth = pdf.internal.pageSize.width * (1 - margin);
const pdfHeight = pdf.internal.pageSize.height * (1 - margin);
const x = pdf.internal.pageSize.width * (margin / 2);
const y = pdf.internal.pageSize.height * (margin / 2);
const widthRatio = pdfWidth / imgProps.width;
const heightRatio = pdfHeight / imgProps.height;
const ratio = Math.min(widthRatio, heightRatio);
const w = imgProps.width * ratio;
const h = imgProps.height * ratio;
pdf.addImage(imgData, "JPEG", x, y, w, h);
Solution 13 - Javascript
There where a lot of solutions with .addImage, I tried many of them, but nothing worked out. So I found the .html() function and after some tries the html2canvas-scale-option. This solution is no general solution, you have to adjust the scale so it will fit your pdf, but this is the only solution, which works for me.
var doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'a4'
});
doc.html(document.querySelector('#styledTable'), {
callback: function (doc) {
doc.save('file.pdf');
},
margin: [60, 60, 60, 60],
x: 32,
y: 32,
html2canvas: {
scale: 0.3, //this was my solution, you have to adjust to your size
width: 1000 //for some reason width does nothing
},
});
Solution 14 - Javascript
convertPhotoImageToPdf(imgPath){
var doc = new jsPDF(undefined, null, null, true);
var imgData = 'data:image/jpeg;base64,'+ imgPath;
doc.addImage(imgData, 'JPEG',10,10,0,0,null,'FAST',0);
//if want add one page
//doc.addPage()
doc.save('testPdf.pdf')
}
Solution 15 - Javascript
Some answers above didn't cover responsive pages for html2canvas. If you need to resize your image based on changing element dimensions use this code:
html2canvas(input, { scrollY: -window.scrollY }).then((canvas) => {
const imgData = canvas.toDataURL('image/jpeg');
const pdf = new jsPDF('p', 'mm', 'a4');
const imgProps = pdf.getImageProperties(imgData);
// doc and image dimensions
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgWidth = imgProps.width;
const imgHeight = imgProps.height;
// claculating right scale to fit the page
const scale = Math.max(pdfHeight / imgHeight, pdfWidth / imgWidth);
const finalWidth = imgWidth * scale;
const finalHeight = imgHeight * scale;
const leftMargin = (pdfWidth - finalWidth) / 2;
// add image with alias and compression of your choice
pdf.addImage( imgData, 'PNG', leftMargin, 0, finalWidth, finalHeight, 'alias', 'FAST');
pdf.save( 'report-name.pdf' );
});
Solution 16 - Javascript
var width = doc.internal.pageSize.width;
var height = doc.internal.pageSize.height;