jsPDF多页面PDF与HTML渲染器

56
我在我的网站上使用jsPDF来生成PDF文件。但现在我有多个DIV要在一个PDF中打印,可能需要2到3页。 例如:

我在网站中使用jsPDF生成PDF,但现在我需要在单个PDF中打印多个DIV,这可能需要2到3页。

例如:

<div id="part1">
  content
</div>

<div id="part2">
  content
</div>

<div id="part2">
   content
</div>

我的JS代码

  • 这个代码能够运行,但并不符合我的预期,它会添加一部分内容(不能在多个页面中包含)。
  • 它会移除像br、h1等的HTML标签。
    function formtoPDF() {
      jsPDF.API.mymethod = function() {
        // 'this' will be ref to internal API object. see jsPDF source
        // , so you can refer to built-in methods like so:
        //   this.line(....)
        //   this.text(....)
      };
      var doc = new jsPDF();
      doc.mymethod();
      var pdfPart1 = jQuery('#genPDFpart1');
      var pdfPart2 = jQuery(".ltinerary");
      var pdfPart3 = jQuery("#domElementHTML");
      var specialElementHandlers = {
        '#loadVar': function(element, renderer) {
          return true;
        }
      };
      doc.fromHTML(pdfPart1.html() + pdfPart3.html() + pdfPart3.html(), 15, 15, {
        'width': 170,
        'elementHandlers': specialElementHandlers
      });
      doc.output('save', 'Download.pdf');
    }

这个问题的解决方案是什么?


1
各位好,有没有解决这个问题的方案? - manipvd
需要将单个图像分割成多个页面怎么办? - Suraz Khanal
我们如何缩放/取消缩放内容以适应页面大小。我的意思是在第一页上使用pdfPart1.html(),在第二页上使用pdfPart2.html(),依此类推。 - programmers_view
11个回答

66

我有同样的工作问题。在搜索了MrRio的GitHub后,我找到了这个链接:https://github.com/MrRio/jsPDF/issues/101

基本上,在添加新内容之前,您必须始终检查实际页面大小。

doc = new jsPdf();
...
pageHeight= doc.internal.pageSize.height;

// Before adding new content
y = 500 // Height position of new content
if (y >= pageHeight)
{
  doc.addPage();
  y = 0 // Restart height position
}
doc.text(x, y, "value");

6
你能否创建一个演示用的代码片段来展示这个? - Shrinivas Pai
1
我猜你应该以某种方式迭代,直到满足你的“高度需求”,而不仅仅是在一个页面中无法容纳元素时添加一页(问题确实说内容可能需要3页)。但无论如何...根据我的经验,“fromHTML”方法已经处理了新页面的创建,尽管在页面更改时会丢失一些内容——这正是我试图搜索的问题。 - DanielM
2
这里的 x 是什么? - tousif Noor
5
好的,已经过去了三年。通过推断,我猜想“x”是水平位置。 - MARC.RS

57

这是一个使用html2canvas和jspdf的示例,尽管生成画布的方式并不重要--我们只会将其高度用作for循环中断点,在此循环中创建新页面并向其添加内容。

在for循环之后,保存PDF文件。

function makePDF() {

   var quotes = document.getElementById('container-fluid');
   html2canvas(quotes).then((canvas) => {
        //! MAKE YOUR PDF
        var pdf = new jsPDF('p', 'pt', 'letter');

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

            window.onePageCanvas = document.createElement("canvas");
            onePageCanvas.setAttribute('width', 900);
            onePageCanvas.setAttribute('height', 980);
            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(612, 791); //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', 20, 40, (width*.62), (height*.62));

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

5
你真棒!我希望我能尽快得到这个答案。 - Tri Nguyen Dung
1
@ITSagar:看看这个更改画布大小的答案:https://dev59.com/cXA75IYBdhLWcg3wMmGo | 不过我不确定为什么你的空白区域是黑色的。在使用这段代码时,我没有遇到这种情况,所以这是一个你需要解决的不同问题。 - Kyle Baker
2
对于那些想要页面边距的人,我通过我的#content的尺寸修改了画布的高度和宽度 var setWidth = 1170; var setHeight = 1514.118; 然后调整了addImage参数 pdf.addImage(canvasDataURL, 'PNG', 40, 40, (width*.62) - 190, (height*.62) - 90); - Rad Apdal
4
你是传奇先生,谢谢。 - Jack Clayton
1
2022年表示感谢! - eamanola
显示剩余8条评论

36

我在这个页面上找到了解决方案:https://github.com/MrRio/jsPDF/issues/434 来自用户:wangzhixuan

我将解决方案复制在这里: // 假设你的图片已经在画布中

      var imgData = canvas.toDataURL('image/png');

      /*
      Here are the numbers (paper width and height) that I found to work. 
      It still creates a little overlap part between the pages, but good enough for me.
      if you can find an official number from jsPDF, use them.
      */
      var imgWidth = 210; 
      var pageHeight = 295;  
      var imgHeight = canvas.height * imgWidth / canvas.width;
      var heightLeft = imgHeight;

      var doc = new jsPDF('p', 'mm');
      var position = 0;

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

      while (heightLeft >= 0) {
        position = heightLeft - imgHeight;
        doc.addPage();
        doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
        heightLeft -= pageHeight;
      }
      doc.save( 'file.pdf');

这是一个完整的示例,使用jsPDF和html2canvas创建pdf中的HTML图像:http://www.techumber.com/2015/04/html-to-pdf-conversion-using-javascript.html,不需要之前的解决方案。 - Jason Glez
谢谢,它可以工作。https://github.com/MrRio/jsPDF/issues/434#issuecomment-145701763 - Tran Son Hoang
谢谢,太棒了。只有一件事,如果你使用点击事件,你必须回到页面顶部。window.scrollTo(0, 0); - Philip
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight, undefined,'FAST');通过此代码,将图像数据以PNG格式添加到文档中,位置为0,大小为imgWidth和imgHeight,未定义压缩质量参数,速度较快。将PDF文件从90MB压缩至3MB,并保持高质量。 - Utkarsh

9
 var doc = new jsPDF('p', 'mm');

 var imgData = canvas.toDataURL('image/png');
 var pageHeight= doc.internal.pageSize.getHeight();
 var pageWidth= doc.internal.pageSize.getWidth();

 var imgheight = $('divName').height() * 25.4 / 96; //px to mm
 var pagecount = Math.ceil(imgheight / pageHeight);

 /* add initial page */
 doc.addPage('l','mm','a4');
 doc.addImage(imgData, 'PNG', 2, 0, pageWidth-4, 0);

 /* add extra pages if the div size is larger than a a4 size */
 if (pagecount > 0) {
     var j = 1;
     while (j != pagecount) {
         doc.addPage('l','mm','a4');
         doc.addImage(imgData, 'PNG', 2, -(j * pageHeight), pageWidth-4, 0);
         j++;
     }
 }

谢谢,这真的很有帮助。 - t3__rry
1
我已经有了初始页面。这个初始的“addPage”只是为我添加了一个空白页。 - Nir O.

4
你可以同时使用html2canvas插件和jsPDF。处理顺序为:HTML转换成PNG,然后PNG转换成PDF。
示例代码:
jQuery('#part1').html2canvas({
    onrendered: function( canvas ) {
        var img1 = canvas.toDataURL('image/png');
    }
});
jQuery('#part2').html2canvas({
    onrendered: function( canvas ) {
        var img2 = canvas.toDataURL('image/png');
    }
});
jQuery('#part3').html2canvas({
    onrendered: function( canvas ) {
        var img3 = canvas.toDataURL('image/png');
    }
});
var doc = new jsPDF('p', 'mm');
doc.addImage( img1, 'PNG', 0, 0, 210, 297); // A4 sizes
doc.addImage( img2, 'PNG', 0, 90, 210, 297); // img1 and img2 on first page

doc.addPage();
doc.addImage( img3, 'PNG', 0, 0, 210, 297); // img3 on second page
doc.save("file.pdf");

3
$( document ).ready(function() {    
$('#cmd').click(function() {
      var options = {
              pagesplit: true //include this in your code
      };
      var pdf = new jsPDF('p', 'pt', 'a4');
      pdf.addHTML($("#pdfContent"), 15, 15, options, function() {
        pdf.save('Menu.pdf');
      });
    });
});

4
虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文信息可以提高其长期价值。 - Thomas Flinkow

1

0
以下是我的代码,但问题在于文档没有分割,无法在新页面中显示文档的其他部分。
请改进这段代码。
<script type='text/javascript'>
$(document).on("click", "#btnExportToPDF", function () {
    var table1 =
    tableToJson($('#table1')[0]),
    cellWidth =42,
    rowCount = 0,
    cellContents,
    leftMargin = 2,
    topMargin = 12,
    topMarginTable =5,
    headerRowHeight = 13,
    rowHeight = 12,
    l = {
        orientation: 'p',
        unit: 'mm',
        format: 'a3',
        compress: true,
        fontSize: 11,
        lineHeight: 1,
        autoSize: false,
        printHeaders: true
    };

    var doc = new jsPDF(l,'pt', 'letter');

    doc.setProperties({
        title: 'Test PDF Document',
        subject: 'This is the subject',
        author: 'author',
        keywords: 'generated, javascript, web 2.0, ajax',
        creator: 'author'
    });
    doc.cellInitialize();

    $.each(table1, function (i, row)
    {
        rowCount++;

        $.each(row, function (j, cellContent) {

            if (rowCount == 1) {
                doc.margins = 1;
                doc.setFont("Times New Roman");
                doc.setFontType("bold");
                doc.setFontSize(11);

                doc.cell(leftMargin, topMargin, cellWidth, headerRowHeight, cellContent, i)
            }
            else if (rowCount == 2) {

                doc.margins = 1;
                doc.setFont("Times ");
                doc.setFontType("normal");
                // or for normal font type use ------ doc.setFontType("normal");

                doc.setFontSize(11);

                doc.cell(leftMargin, topMargin, cellWidth, rowHeight, cellContent, i);
            }
            else {

                doc.margins = 1;
                doc.setFont("Times  ");
                doc.setFontType("normal ");
                doc.setFontSize(11);
                doc.cell(leftMargin, topMargin, cellWidth, rowHeight, cellContent, i);
                // 1st=left margin    2nd parameter=top margin,     3rd=row cell width      4th=Row height
            }
        })
    })
    doc.save('sample Report.pdf');
});

function tableToJson(table) {

    var data = [];

    // first row needs to be headers
    var headers = [];

    for (var i=0; i<table.rows[0].cells.length; i++) {
        headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
    }

    // go through cells
    for (var i=1; i<table.rows.length; i++) {

        var tableRow = table.rows[i];

        var rowData = {};

        for (var j=0; j<tableRow.cells.length; j++) {
            rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
        }

        data.push(rowData);
    }

    return data;
}
</script>

0

自动不将数据分成多个页面。您可以手动拆分。

如果您的(rowCount * rowHeight)> 420mm(A3高度,以毫米为单位),请添加新页面功能。(抱歉,我无法在运行时编辑您的代码) 添加新页面后,leftMargin,topMargin = 0;(重新开始) 我已经将示例代码与您的代码合并。希望这是正确的。

else {
    doc.margins = 1;
    doc.setFont("Times  ");
    doc.setFontType("normal ");
    doc.setFontSize(11);
    if ( rowCount * rowHeight > 420 ) {
        doc.addPage();
        rowCount = 3; // skip 1 and 2 above
    } else {
        // now rowcount = 3 ( top of new page for 3 )
        // j is your x axis cell index ( j start from 0 on $.each function ) or you can add cellCount like rowCount and replace with
        // rowcount is your y axis cell index
        left = ( ( j ) * ( cellWidth + leftMargin );
        top = ( ( rowcount - 3 ) * ( rowHeight + topMargin );
        doc.cell( leftMargin, top, cellWidth, rowHeight, cellContent, i);
        // 1st=left margin    2nd parameter=top margin,     3rd=row cell width      4th=Row height
    }
}

您可以直接将HTML转换为无损PDF。 HTML => PDF示例的Youtube视频


0
         html2canvas(element[0], {
                    onrendered: function (canvas) {
                        pages = Math.ceil(element[0].clientHeight / 1450);
                        for (i = 0; i <= pages; i += 1) {
                            if (i > 0) {
                                pdf.addPage();
                            }
                            srcImg = canvas;
                            sX = 0;
                            sY = 1450 * i;
                            sWidth = 1100;
                            sHeight = 1450;
                            dX = 0;
                            dY = 0;
                            dWidth = 1100;
                            dHeight = 1450;
                            window.onePageCanvas = document.createElement("canvas");
                            onePageCanvas.setAttribute('width', 1100);
                            onePageCanvas.setAttribute('height', 1450);
                            ctx = onePageCanvas.getContext('2d');
                            ctx.drawImage(srcImg, sX, sY, sWidth, sHeight, dX, dY, dWidth, dHeight);
                            canvasDataURL = onePageCanvas.toDataURL("image/png");
                            width = onePageCanvas.width;
                            height = onePageCanvas.clientHeight;
                            pdf.setPage(i + 1);
                            pdf.addImage(canvasDataURL, 'PNG', 35, 30, (width * 0.5), (height * 0.5));
                        }
                        pdf.save('testfilename.pdf');
                    }
                });

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