如何使用jspdf将图像保存在多个pdf页面中

16

我有一张表格(列对齐方式不同),需要保存为pdf格式。我使用html2canvas将表格转换为图片,然后使用jspdf将图片保存为pdf。如果图像大小小于或等于pdf页面大小,则工作正常;但是,如果图像大小大于页面大小,则仅保存pdf的第一页(其中只有部分图像),其余部分图像不会显示/保存在pdf中。这是我使用的javascript代码。

       $("#btnVC_saveGLSummary").click(function () {
        html2canvas($("#tblSaveAsPdf1"), {
        onrendered: function (canvas) {
        var myImage = canvas.toDataURL("image/jpeg");            
        var d = new Date().toISOString().slice(0, 19).replace(/-/g, "");
        filename = 'report_' + d + '.pdf';
        var doc = new jsPDF();
        doc.addImage(myImage, 'JPEG', 12, 10);
        doc.save(filename);
          }
         });
       });

有什么办法可以获取pdf第二页上图像的剩余部分?

7个回答

43

它适用于html2canvas和jspdf。

var imgData = canvas.toDataURL('image/png');
var imgWidth = 210; 
var pageHeight = 295;  
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm');
var position = 10; // give some top padding to first page

doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;

while (heightLeft >= 0) {
  position += heightLeft - imgHeight; // top padding for other pages
  doc.addPage();
  doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
  heightLeft -= pageHeight;
}
doc.save( 'file.pdf');

1
非常好,谢谢。只有一个小问题,请添加 position += heightLeft - imgHeight; 以在下一页中添加一些顶部填充。 - Furkat U.
12
我认为第三页及其后续页面的位置计算存在错误。赋值语句中的“+=”,也就是position += heightLeft - imgHeight,导致了pageHeight被减少了两次。因此,位置从0、-295、-590等变成了0、-295、-885等。解决方法很简单,只需要使用赋值符号“=”来计算位置,即position = heightLeft - imgHeight;或者在循环中用以下代码替换位置计算:x= x+1;position = (pageHeightx)-1; 希望这能帮助到某些人。 - Lew Perren
如何根据图像设置PDF页面大小,在此之后创建新页面和新图像。 - Manmeet Khurana
1
我认为它应该是 position = heightLeft - imgHeight + 10(第一页的原始填充会导致后续页面偏移10)。 - Alba Hoo

14

我使用这种方法

function makePDF(){
var quotes = document.getElementById('container-fluid');
html2canvas(quotes, {
    onrendered: function(canvas) {
    //! MAKE YOUR PDF
    var pdf = new jsPDF('p', 'pt', 'a4');

    for (var i = 0; i <= quotes.clientHeight/980; i++) {
        //! This is all just html2canvas stuff
        var srcImg  = canvas;
        var sX      = 0;
        var sY      = 1120*i; // start 980 pixels down for every new page
        var sWidth  = 778;
        var sHeight = 1120;
        var dX      = 0;
        var dY      = 0;
        var dWidth  = 778;
        var dHeight = 1120;

        window.onePageCanvas = document.createElement("canvas");
        onePageCanvas.setAttribute('width', 778);
        onePageCanvas.setAttribute('height', 1120);
        var ctx = onePageCanvas.getContext('2d');
        // details on this usage of this function: 
        // https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
        ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);

        // document.body.appendChild(canvas);
        var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);

        var width         = onePageCanvas.width;
        var height        = onePageCanvas.clientHeight;

        //! If we're on anything other than the first page,
        // add another page
        if (i > 0) {
            pdf.addPage(595, 842); //8.5" x 11" in pts (in*72)
        }
        //! now we declare that we're working on that page
        pdf.setPage(i+1);
        //! now we add content to that page!
        pdf.addImage(canvasDataURL, 'PNG', 0, 0, (width*.72), (height*.71));

    }
    //! after the for loop is finished running, we save the pdf.
    pdf.save('Test3.pdf');
  }
  });
  }

我希望它会有所帮助

受另一个堆栈溢出的回答启发


1
它报错了:类型“Window”上不存在属性“onePageCanvas”,以及找不到名称“onePageCanvas”。并创建一个空白内容的PDF。 - Bharti Ladumor
1
如果您不是在常规浏览器上下文中使用它,则window对象不可用。请改用var onePageCanvas =将其声明为循环范围内的局部变量。 - ben_weller
看起来它类似于真实的源代码 https://dev59.com/amIk5IYBdhLWcg3wbtyb - ßiansor Å. Ålmerol

1
这个问题在之前已经有类似的回答了,但我觉得可以举一个例子,省略不必要的代码:
您可以通过以下方式轻松地遍历所有页面,并在每个页面上添加“水印”文本或其他内容:
let pdf = new jspdf();
// do something that creates multiple pages
for (let pageNumber = 1; pageNumber <= pdf.getNumberOfPages(); pageNumber++) {
  pdf.setPage(pageNumber)
  pdf.addImage('myImgOnEveryPage.png', 10,10,20,20);
  pdf.text('My text on every page, 12, 12);
}

(JSPDF 版本 2.1.1)

这个使用html2canvas吗?还是不需要它? - NightTom

0

您可以通过在自己的代码中添加小的调整来轻松实现此操作。

$("#btnVC_saveGLSummary").click(function () {
    html2canvas($("#tblSaveAsPdf1"), {
    onrendered: function (canvas) {
    var myImage = canvas.toDataURL("image/jpeg");            
    var d = new Date().toISOString().slice(0, 19).replace(/-/g, "");
    filename = 'report_' + d + '.pdf';
    var doc = new jsPDF();
    var totalPages = doc.internal.getNumberOfPages();
    for(let i = 1; i < totalPages; i++) {
        doc.setPage(i);
        doc.addImage(myImage, 'JPEG', 12, 10);
    }       
    doc.save(filename);
    }
  });
});

0
你也可以通过以下方式实现这一点;
const doc = new jsPDF('p', 'mm');
const imgData = canvas.toDataURL('image/png');
const imgWidth = 210; 
const pageHeight = doc.internal.pageSize.getHeight();  
const imgHeight = (canvas.height * imgWidth) / canvas.width;
const totalPageSize = Math.ceil(imgHeight / pageHeight);
let yPosition = 10;

doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);

for (let pageIndex = 1; pageIndex < totalPageSize; pageIndex++) {
  // making it negative to crop the image
  // and adding 10 because of the initial padding
  yPosition = pageIndex * pageHeight * -1 + 10; 
  doc.addPage();
  doc.addImage(
    imgData,
    'PNG',
    0,
    yPosition,
    imageWidth,
    imageHeight
  );
}

doc.save( 'file.pdf');

0
                var ctx = canvas.getContext("2d");
                ctx.drawImage(image, 0, 1025, sectionWidth, 1250, 0, 0, 1800, 950);
                var image2 = new Image();
                image2 = Canvas2Image.convertToJPEG(canvas);
                image2Data = image2.src;
                doc.addImage(image2Data, 'JPEG', -105, 5, 440, 325);

基本上,您可以获取画布的上下文,然后使用drawImage函数创建一个新图像,该图像是原始画布的一部分。 drawImage的参数包括:

drawImage(img, startX, startY, originalW, originalH, destX, dextY, destW, destH);

其中,startX和Y是原始图像剪切的起始位置,original W和H是剪切区域的高度和宽度(在原始图片上),即要剪切多少,destX和Y是新剪切放置在PDF上的位置,而destH和W定义了放置在画布上的剪切大小(一旦剪切完成,它们会拉伸图像)
希望这有所帮助,
祝好


1
那如何展示多个页面? - Jerther

0

函数React将多个组件转换为PDF文件

  const ids = ["id1", "id2", "id3"]; // list id component want to export



const handleExport = useCallback(async () => {
setIsLoading(true);

const pdf = jsPDF("p", "pt", "a4");
let allHeight = 0;

const canvasPromises = ids.map(async (id) => {
  // ! change to state id
  setIsLoading(true);

  const element = document.getElementById(id);
  const canvas = await html2canvas(element);
  const img = canvas.toDataURL("image/png");
  const imgProperties = pdf.getImageProperties(img);
  const pdfWidth = pdf.internal.pageSize.getWidth();
  const pdfHeight =
    (imgProperties.height * pdfWidth) / imgProperties.width;

  if (allHeight > 700) {  // heigth over a4 heigth add page for pdf
    allHeight = 5;
    pdf.addPage(1);
  }

  pdf.addImage(
    img,
    "PNG",
    0,
    allHeight,
    pdfWidth - 5,
    pdfHeight,
    id,
    "FAST",
  );

  allHeight += pdfHeight + 5;
});
const dataField = await Promise.all(canvasPromises).then(
  (res) => res,
);

pdf.save(`${title}-${new Date().toLocaleString()}.pdf`);
setIsLoading(false);
return dataField; 
}, [ids]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接