如何使用jsPDF在PDF中显示跨两页的图像?

11

我有一个HTML页面,在这个页面上有一个按钮。当我点击这个按钮时,它会使用html2canvas将整个HTML页面转换成数据图像,并使用jsPDF库将其放置在PDF中。我使用的JavaScript代码如下:

```javascript [原来的JavaScript代码] ```
$("#printButton").click(function(){
html2canvas([document.getElementById('form1')], {
        onrendered: function (canvas) {
            var imageData = canvas.toDataURL('image/jpeg',1.0); 
           var doc = new jsPDF('landscape');
           doc.addImage(imageData,'JPEG',5,20,200,150);
           doc.save('Test.pdf');
     }
    });
});

它只在第一页显示图像。但是当HTML页面大小更大时,我想要剪切图像数据并将其放置在PDF的两个页面中。请帮我解决这个问题。


2
那个问题有进展了吗?我也遇到了类似的问题,计划使用画布将图像分割成几部分,然后放置在不同的页面上。 - Naz
不要在创建图像后对其进行切片,而是将您的HTML分成多个div并转换为图像,然后逐个放置。这是我作为替代方案正在做的事情。 - Manoj Nayak
8个回答

6
html2canvas($('#wrap')[0]).then(canvas => {
        try {
            contentH = $('#wrap').height();
            var img = canvas.toDataURL("image/png", 1.0);
            $w = $actw = canvas.width;
            $h = $acth = canvas.height;
            var pdf = new jsPDF("p", "mm", "a4");
            var width = $maxw = pdf.internal.pageSize.width;
            var height = $maxh = pdf.internal.pageSize.height;
            if (!$maxw) $maxw = width;
            if (!$maxh) $maxh = height;
            if ($w > $maxw) {
                $w = $maxw;
                $h = Math.round($acth / $actw * $maxw);
            }
            pdf.addImage(img, 'JPEG', 0, 0, $w, $h);
            $count = Math.ceil($h) / Math.ceil($maxh);
            $count = Math.ceil($count);
            for (var i = 1; i <= $count; i++) {
                position = - $maxh * i
                alert(position);
                pdf.addPage(img, 'JPEG', 0, 0, $w, $h);
                pdf.addImage(img, 'JPEG', 0, position, $w, $h);
            }
            pdf.save("cart.pdf");
        } catch (e) {
            alert("Error description: " + e.message);
        }
    });

1
以上解决方案会在文档末尾添加一个空白页。我已经编辑了代码以删除它。我使用了以下代码替换了计算_$count_变量的2行代码(_$count = Math.ceil($h) / Math.ceil($maxh);$count = Math.ceil($count);):$count = Math.ceil($h / $maxh) - 1;_ - Victor
@Victor,你能否在生成PDF时查看一下,第二页的数据没有填充的问题?https://stackoverflow.com/questions/63378768/jspdf-multiple-page-data-is-getting-cropped - Gokul

5

这可能不是完美的答案,但仍然有效。

                $("#btnSaveAsPDF").click(function () {
                html2canvas($("#tblSaveAsPdf_canvas"), {
                onrendered: function (canvas) {
                var imageData = canvas.toDataURL("image/jpeg");
                var image = new Image();
                image = Canvas2Image.convertToJPEG(canvas);
                var doc = new jsPDF();
                doc.addImage(imageData, 'JPEG', 12, 10);
                var croppingYPosition = 1095;
                count = (image.height) / 1095;

                for (var i =1; i < count; i++) {
                        doc.addPage();
                        var sourceX = 0;
                        var sourceY = croppingYPosition;
                        var sourceWidth = image.width;
                        var sourceHeight = 1095;
                        var destWidth = sourceWidth;
                        var destHeight = sourceHeight;
                        var destX = 0;
                        var destY = 0;
                        var canvas1 = document.createElement('canvas');
                        canvas1.setAttribute('height', destHeight);
                        canvas1.setAttribute('width', destWidth);                         
                        var ctx = canvas1.getContext("2d");
                        ctx.drawImage(image, sourceX, 
                                             sourceY,
                                             sourceWidth,
                                             sourceHeight, 
                                             destX, 
                                             destY, 
                                             destWidth, 
                                             destHeight);
                        var image2 = new Image();
                        image2 = Canvas2Image.convertToJPEG(canvas1);
                        image2Data = image2.src;
                        doc.addImage(image2Data, 'JPEG', 12, 10);
                        croppingYPosition += destHeight;              
                    }                  
                var d = new Date().toISOString().slice(0, 19).replace(/-/g, "");
                filename = 'report_' + d + '.pdf';
                doc.save(filename);
            }

        });
    });

当我应用这个转换时,第二页是黑色的。 - Victor

3
我已更新代码。现在可以处理多个页面,并且可以更精确地裁剪图像,而不会出现裁剪后图像末尾的黑色背景。
代码
$('#pdf').on('click', function(){

    html2canvas(document.body, {
        onpreloaded: function(){
              $("#barra").hide(); 
        },
        onrendered: function(canvas) {
            $("#page").hide();
            var imgData = canvas.toDataURL('image/jpeg');              
            options = {
                orientation: "0",
                unit: "mm",
                format: "a4"
            };
            var doc = new jsPDF(options, '', '', '');
            doc.addImage(imgData, 'jpeg', 10, 10, 190, 0);
            var corte = 1620; // configura tamanho do corte
            var image = new Image();
            image = Canvas2Image.convertToJPEG(canvas);

            var croppingYPosition = corte;
            var count = (image.height)/corte;


            for (var i =1; i < count; i++) {
                    doc.addPage();
                    var sourceX = 0;
                    var sourceY = croppingYPosition;
                    var sourceWidth = image.width;
                    var sourceHeight = corte;
                    var destWidth = sourceWidth;
                    var destHeight = sourceHeight;
                    var destX = 0;
                    var destY = 0;
                    var canvas1 = canvas;
                    canvas1.setAttribute('height', (image.height)-(corte*i));
                    canvas1.setAttribute('width', destWidth);                         
                    var ctx = canvas1.getContext("2d");
                    ctx.drawImage(image, sourceX, 
                                         sourceY,
                                         sourceWidth,
                                         sourceHeight, 
                                         destX, 
                                         destY, 
                                         destWidth, 
                                         destHeight);
                    var image2 = new Image();
                    image2 = Canvas2Image.convertToJPEG(canvas1);
                    image2Data = image2.src;
                    doc.addImage(image2Data, 'JPEG', 10, 10, 190, 0);
                    croppingYPosition += destHeight;              
                }     


            doc.save('sample-file.pdf');
            $('canvas').remove();
            $('canvas1').remove();
            $("#page").show();
            $("#barra").show();
        }
    });
});

它的行为与user3687972的解决方案相同:在结尾添加了黑色部分,并且只打印了部分文档。@moknisofien的解决方案非常好用。 - Victor

3
要在多个页面上放置一张长图,我想到了以下方法:
var img = new Image();
img.onload = function(){
    while (croppingYPosition < image.height) {
        var sourceX = 0;
        var sourceY = croppingYPosition;
        var sourceWidth = image.width;
        var sourceHeight = maxHeight;
        var leftToCropHeight = image.height - croppingYPosition;
        if (leftToCropHeight < maxHeight) {
            sourceHeight = leftToCropHeight;
        }
        var destWidth = sourceWidth;
        var destHeight = sourceHeight;
        var destX = 0;
        var destY = 0;
        var canvas = document.createElement('canvas');
        canvas.setAttribute('height', destHeight);
        canvas.setAttribute('width', destWidth);
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 
                        sourceX,
                        sourceY,
                        sourceWidth,
                        sourceHeight,
                        destX,
                        destY,
                        destWidth,
                        destHeight);
        croppedImages.push(CanvasToJPEGConversionService.toJPEG(canvas));
        croppingYPosition += destHeight;
    }
    retur croppedImages;
};
img.src = image.dataURL;

我基本上得到了一个包含数据URL(裁剪后的图像)的对象数组。


2

我曾经遇到黑屏问题,但找到了解决方案,它非常简单且有效。

html2canvas($("#testId")[0], { allowTaint: true }).then(function (canvas) {
        try {
            var imgData = canvas.toDataURL('image/jpeg');
            let options = {
                orientation: "0",
                unit: "mm",
                format: "a4"
            };
            var doc = new jsPDF(options, '', '', '');
            doc.addImage(imgData, 'jpeg', 0, 0, 210, 0);
            var corte = 1680;
            var image = canvas.toDataURL('image/jpeg');
            var count = (canvas.height) / corte;
            for (var i = 1; i < count; i++) {
                doc.addPage();
                doc.addImage(image, 'JPEG', 0, -330 * i, 210, 0);
            }
            doc.save('sample-file.pdf');
            } catch (e) {
            console.log('error pdf', e);
        }
  

2
      var pdf = new jsPDF();
      pdf.addImage(image1, 'JPEG', 10, 10);
      pdf.addImage(image2, 'JPEG', 10, 90);
      pdf.addImage(image3, 'JPEG', 10, 170)
      pdf.addPage();
      pdf.addImage(image4, 'JPEG', 10, 10)
      pdf.addImage(image5, 'JPEG', 10, 140)
      pdf.save("download.pdf");

你应该对你的答案进行一些解释。 - Mikev
pdf.addPage(); 这个方法用于在jsPDF中添加新页面。 - Upendra Kumar Pandey

1
我想到了一个解决方案,希望能对你有所帮助:
PDFConverter.prototype.exportToPDF = function (divID, filename, pdfHeight) {

html2canvas($('#' + divID), {                                       //Plugin:html2canvas.min.js,Takes html and convert to canvas.

    onrendered: function (canvas) {
        var doc = new jsPDF();                                    //Plugin:jspdf.min.js Using to export html to pdf file
        var HtmltoPdfPageHeight;
        if (pdfHeight)
            HtmltoPdfPageHeight = pdfHeight;
        var image = new Image();
        image = Canvas2Image.convertToJPEG(canvas);

        var croppingYPosition;
        var count = Math.ceil((image.height) / HtmltoPdfPageHeight);


        for (var i = 1; i <= count; i++) {

            if (i == 1) 
                croppingYPosition = 0;
            else 
                doc.addPage();


            var sourceX = 0;
            var sourceY = croppingYPosition;

            var croppingImageHeight = (image.height - (HtmltoPdfPageHeight * (i-1))) > HtmltoPdfPageHeight ? HtmltoPdfPageHeight : (image.height - (HtmltoPdfPageHeight * (i-1)));
            var destX = 0;
            var destY = 0;
            var croppedCanvas = document.createElement('canvas'); //Canvas using to resize main canvas
            croppedCanvas.setAttribute('height', croppingImageHeight);
            croppedCanvas.setAttribute('width', image.width);
            var ctx = croppedCanvas.getContext("2d");
            ctx.drawImage(image, sourceX,                                //drawImage(img, startX, startY, originalW, originalH, destX, destY, destW, destH);
                                 sourceY,
                                 image.width,
                                 HtmltoPdfPageHeight,
                                 destX,
                                 destY,
                                 image.width,
                                 HtmltoPdfPageHeight);
            var imageToAddatPdf = new Image(); //Final image exporting in pdf page
            imageToAddatPdf = Canvas2Image.convertToJPEG(croppedCanvas);
            doc.addImage(imageToAddatPdf.src, 'JPEG', 10, 10, 185, 0);
            croppingYPosition += HtmltoPdfPageHeight;
        }

        doc.save(filename + '.pdf');



    }
 });
};

0

适合跨多个页面的长图

首先将文档实例设置为接受单位为“pt”。接下来的步骤是检查图像是否大于页面大小,如果是,则图像将跨越多个页面。由于我们有docHeight,因此我们将能够获取包含在当前页面中的图像部分。现在,为下一页重复此操作(剩余图像再次变大)。代码如下所示(在此,我希望图像仅占用0.8页宽,高度相应调整):

  //Read Canvas to be exported
  const appRolesElement = document.getElementById('app-roles-element');
  const appRolesCanvas = await html2canvas(appRolesElement, { onclone: function (document) {
      //Different style requirement for export
      document.querySelectorAll('.right-wrapper').forEach(el => {
        el.style.marginLeft = '0px';
      })
  }});

  const doc = new jsPDF({
    compress: true,
    orientation: 'p',
    unit: 'pt',
    format: 'a4'
  });
  var docWidth = doc.internal.pageSize.getWidth();
  var docHeight = doc.internal.pageSize.getHeight();
  let heightInPlace = 0;
  let appRolesImageDisplayHeight = getDisplayHeight(appRolesCanvas.height, appRolesCanvas.width, docWidth*0.8);
  let appRolesIterationCounter = 0;
  let appRolesSourceClipStartY = 0;

  //Keep checking if a new page is required
  while(appRolesImageDisplayHeight > 0) {
    if(appRolesIterationCounter > 0) {
      doc.addPage();
      heightInPlace = 10;
    }
    ++appRolesIterationCounter;
    const remainingHeightInPage = docHeight - heightInPlace;
    const sourceHeightToBeDisplayed = getSourceHeight(remainingHeightInPage, appRolesCanvas.width, docWidth);
    const clippedImage = await convertURIToImageData(appRolesImage, appRolesCanvas.width, sourceHeightToBeDisplayed, appRolesSourceClipStartY);
    doc.addImage(clippedImage, 'JPEG', 10, heightInPlace, docWidth * 0.8, remainingHeightInPage * 0.8);
    heightInPlace += (remainingHeightInPage * 0.8) + 5;
    appRolesImageDisplayHeight = appRolesImageDisplayHeight - remainingHeightInPage;
    appRolesSourceClipStartY += sourceHeightToBeDisplayed;
  }
  doc.save("export.pdf");


  const getDisplayHeight = (sourceHeight, sourceWidth, displayWidth) => {
    return (displayWidth/sourceWidth)*sourceHeight;
  };

  const getSourceHeight = (displayHeight, sourceWidth, displayWidth) => {
    return displayHeight*(sourceWidth/displayWidth);
  }

此外,请使用属性 data-html2canvas-ignore 忽略导出的内容。

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