【问题标题】:Multipage pdf with html2Canvas带有 html2Canvas 的多页 pdf
【发布时间】:2018-05-11 18:42:49
【问题描述】:

我正在使用 react-typescript 并且我已经在这个参考的帮助下成功地从一个 html 页面创建了一个 PDF 文件 Generating a PDF file from React Components

但是,如果我们想创建一个包含多个页面的 PDF,那么该怎么做呢? 使用 a4 大小的页面,所有边都有适当的边距,并且在每个新页面中都应该应用边距。

这是我的代码。

private printDocument() {
        const input = document.getElementById("pdf");

        html2canvas(input)
            .then((canvas) => {
                const pdf = new jsPDF("p", "px", "a4");
                pdf.addHTML(input, 0, 0, {
                    pagesplit: true,
                    background: "#ffffff",
                }, () => {
                    pdf.save("download.pdf");
                });
            });
    }

请帮我看看它的银色。 提前谢谢你

【问题讨论】:

    标签: jspdf html2canvas html2pdf


    【解决方案1】:

    你试试?

    const printDocument= () => {
    const input = document.getElementById('divToPrint');
    const input2 = document.getElementById('divToPrint2');
    const pdf = new jsPDF();
    
    html2canvas(input)
      .then((canvas) => {
        const imgData = canvas.toDataURL('image/png');
        pdf.addImage(imgData, 'JPEG', 0, 0);
        pdf.addPage();
        html2canvas(input2)
          .then((canvas2) => {
            const imgData2 = canvas2.toDataURL('image/png');
            pdf.addImage(imgData2, 'JPEG', 0, 0);
            pdf.save("download.pdf");
          })
        ;
      })
    ;
    

    }

    【讨论】:

      【解决方案2】:

      我尝试使用 jsPDF 来解决这个问题,但我没有成功。我不清楚 jsPDF 管理分页内容的方式。 所以我决定使用另一个很棒的 js 库 pdfMake。 我在这个问题中得到了这些信息:Generating PDF files with JavaScript

      在您提到的问题 (Generating a PDF file from React Components) 中,最佳答案是处理分页的好方法。您为每个页面创建一个 div。但就我而言,我的内容可以动态地增加你的垂直尺寸,所以我无法修复 div 的垂直尺寸。 所以,我确实喜欢这样:

      printDocument() {
        const divs = document.getElementsByClassName('example');
        const newList = [].slice.call(inputs);
        var contentArray = []
        var docDefinition = {
                  pageSize: {width: 800, height: 1173},
                  content: [
                      {
                          text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.'
                      }
                  ]
                  
              }
              
        Promise.map(newList, async (element, index) => {
                  let canvas = await html2canvas(element);
                  const imgData = await canvas.toDataURL('image/png');
                  // console.log("imgData URL => ", imgData)
                  // margin horizontal -40 = removing white spaces
                  return contentArray[`${index}`] = [{ image: imgData, width: canvas.width, height: canvas.height, margin: [-40, 0] }, {
                      text: ` ${index} - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi.`
      }];
                 
              }).then(
                  () => ( docDefinition.content.push(contentArray))
              ).then(
                  () => {
                      console.log("... starting download ...")
                      pdfMake.createPdf(docDefinition).download('examplePdf.pdf')
                  } 
              )
      }
      
      // In your react's component constructor ... 
      
      constructor(props) {
              super(props);
              this.printDocument = this.printDocument.bind(this)
      }
      
      // the imports below ...
      import Promise from 'bluebird';
      import html2canvas from 'html2canvas';
      import pdfMake from 'pdfmake/build/pdfmake.js';
      import pdfFonts from "pdfmake/build/vfs_fonts.js";
      pdfMake.vfs = pdfFonts.pdfMake.vfs;
      
      // i'm using these middlewares
      import promise from 'redux-promise'
      import multi from 'redux-multi'
      import thunk from 'redux-thunk'
      <div>
        The approach here is: a div it's not a page. Because if the image generated by the canvas element it's bigger than the page vertical size, we'll need to control the pagination by ourselves. So, we broke our content in small elements to the pdf generator handle the pagination to us. This way we garantee that the pagination will occurs without cuts. 
        <div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >
        
        // any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.
        
        </div>
        <div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >
        
        // any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.
        
        </div>
        <div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >
        
        // any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.
        
        </div>
        
      </div>
      
      <div>
       <button onClick={this.printDocument}> print using PDFMake  </button>
      </div>

      将 bluebird 的 Promise.map 与 async/await 资源一起使用,我们可以确保我们将等到画布中所有图像的生成结束。此过程可能需要一段时间,具体取决于您的图片大小。

      http://bluebirdjs.com/docs/api/promise.map.html

      看一下pdfMake的github: https://github.com/bpampuch/pdfmake

      还有他的游乐场,里面有很好的例子和如何做: http://pdfmake.org/playground.html

      我仍然会尝试升级这种方式来解决分页问题,​​但这是我解决问题的最快方式,我希望对某人有用。

      【讨论】:

        猜你喜欢
        • 2019-12-28
        • 2019-11-27
        • 2020-07-12
        • 1970-01-01
        • 2014-05-11
        • 1970-01-01
        • 2021-08-26
        • 2016-04-05
        • 2015-01-18
        相关资源
        最近更新 更多