How to set image to fit width of the page using jsPDF?

JavascriptJspdf

Javascript 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;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionsreeraj nyrosView Question on Stackoverflow
Solution 1 - JavascriptPurushothView Answer on Stackoverflow
Solution 2 - JavascriptPhilipView Answer on Stackoverflow
Solution 3 - JavascriptzerzevulView Answer on Stackoverflow
Solution 4 - Javascriptcarbon1479View Answer on Stackoverflow
Solution 5 - JavascriptMax AknView Answer on Stackoverflow
Solution 6 - JavascriptthephperView Answer on Stackoverflow
Solution 7 - JavascriptWeihui GuoView Answer on Stackoverflow
Solution 8 - JavascriptIgor RyanView Answer on Stackoverflow
Solution 9 - JavascriptvohrahulView Answer on Stackoverflow
Solution 10 - JavascriptRavi GuruView Answer on Stackoverflow
Solution 11 - JavascriptPriyanshu ChauhanView Answer on Stackoverflow
Solution 12 - JavascriptChrisView Answer on Stackoverflow
Solution 13 - JavascriptMoppieMopView Answer on Stackoverflow
Solution 14 - JavascriptEdwardMosesView Answer on Stackoverflow
Solution 15 - JavascriptRafalView Answer on Stackoverflow
Solution 16 - JavascriptAriel FernándezView Answer on Stackoverflow