如何使用jsPDF设置图像以适应页面宽度?

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

有什么办法可以解决吗? 我试图以毫米为单位设置宽度和高度。如何将其设置为全角?

您可以像下面这样获取PDF文档的宽度和高度,

var doc = new jsPDF("p", "mm", "a4");

var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();

然后您可以将此宽度和高度用于您的图像以适合整个 PDF 文档。

var imgData = 'data:image/jpeg;base64,/9j/4AAQSkZJ......';

doc.addImage(imgData, 'JPEG', 0, 0, width, height);

确保您的图像与 PDF 文档具有相同的大小(分辨率)。否则它看起来会变形(拉伸)。

如果您想将 px 转换为 mm,请使用此 link http://www.endmemo.com/sconvert/millimeterpixel.php

我的回答涉及您所问问题的更具体案例,但我认为可以从中得出一些想法以更普遍地应用。另外,如果可以的话,我会 post 将此作为对 Purushoth 的回答(我的回答基于此)的评论。

好的,所以我的问题是如何在不丢失宽高比的情况下使网页适合 pdf 文档。我将 jsPDF 与 html2canvas 结合使用,并根据 div 的宽度和高度计算出比率。我将相同的比例应用于 pdf 文档,页面完全适合页面,没有任何失真。

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.
     }
});

我遇到了同样的问题,但我用这段代码解决了

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');
                }
            }) 

更好的解决方案是使用图像的纵横比设置文档 width/height。

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>

我今天早上在试验 html2canvas 时发现了这一点。虽然这不包括打印多页的规定,但它确实将图像缩放到页面宽度并根据调整后的宽度重新调整高度:

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');
    });

自此 commit 以来 API 发生了变化,现在使用的是 1.4.1 版本

var width = pdf.internal.pageSize.getWidth();
var height = pdf.internal.pageSize.getHeight();

如果只有一张图片,很容易适应页面。更具挑战性的任务是将各种尺寸的图像适合 pdf 文件。归档的关键是计算图像的纵横比和页面的相对 width/height 比例。下面的代码是我用来将多张图片在线转换为PDF文件的代码。它将根据 images/page 的方向旋转图像并设置适当的边距。我的项目使用带有在线 src 的图像。您应该可以根据自己的需要进行修改。

关于图片旋转,如果旋转后出现空白页,可能只是图片越界了。有关详细信息,请参阅此 answer

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.

如果您需要获取 PDF 文件的 宽度 100%自动高度 您可以使用 getImageProperties 属性 html2canvas

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');
      });

如果你想让动态尺寸的图片自动尽可能多地填充页面并且仍然保持图片width/height-ratio,你可以这样做:

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,
)

这就是我在 Reactjs 中取得的成就。

主要问题是比率和比例如果您快速 window.devicePixelRatio,它的默认值是 2,这会导致一半的图像问题。

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.
  })
}

所有屏幕尺寸和动态方向的解决方案:

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')
  })
}

我的解决方案是根据 pdf 方向和图像大小检查需要应用什么比例(高度或宽度)。注意:如果不需要保证金,则设置保证金为0。

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

那里有很多 .addImage 的解决方案,我尝试了很多,但没有成功。 所以我找到了 .html() 函数,并在尝试了一些 html2canvas-scale-option 之后。 此解决方案不是通用解决方案,您必须调整比例以使其适合您的 pdf,但这是唯一适合我的解决方案。

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
    },
});
        var width = doc.internal.pageSize.width;    
        var height = doc.internal.pageSize.height;
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')
}

上面的一些答案没有涵盖 html2canvas 的响应页面。如果您需要根据更改的元素尺寸调整图像大小,请使用此代码:

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' );
});