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

后端 未结 11 2093
醉话见心
醉话见心 2020-12-04 21:37

Is there any way to solve this? I tried to set width and height in mm. How can I set it to full-width?

相关标签:
11条回答
  • 2020-12-04 22:01

    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');
          });
    
    0 讨论(0)
  • 2020-12-04 22:03

    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.
      })
    }
    
    0 讨论(0)
  • 2020-12-04 22:07

    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');
        });
    
    0 讨论(0)
  • 2020-12-04 22:07

    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.

    0 讨论(0)
  • 2020-12-04 22:09

    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')
      })
    }
    
    0 讨论(0)
  • 2020-12-04 22:13

    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,
    )
    
    0 讨论(0)
提交回复
热议问题