Multipage pdf with html2Canvas

I am using response-typescript and I have successfully created a PDF file from an html page using this link Creating a PDF file from React Components

But if we want to create a PDF with multiple pages, what should we do? with an a4 size page with corresponding margins on all sides and on each new page to be applied.

And here is my code.

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

please help me with his argentinian. Thank you in advance

+2
source share
1 answer

I tried using jsPDF to solve this problem, but I failed. The way jsPDF manages content to split in page mode is not clear to me. So I decided to use pdfMake, another awesome js library. I got this information in this question: Creating PDF files using JavaScript

In the question you pointed out ( Creating a PDF from React Components ), the best answer is the best way to deal with pagination. You create a div for each page. But in my case, my content can dynamically increase your vertical size, so I cannot fix the size of vertical divs. So I liked it:

 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 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 not a page. Because if the image generated by the canvas element it 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 height size it not bigger than the your PDF doc 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 height size it not bigger than the your PDF doc 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 height size it not bigger than the your PDF doc height dimension, else your div may never be rendered inside it. </div> </div> <div> <button onClick={this.printDocument}> print using PDFMake </button> </div> 

Using Promise.map 's Promise.map with async / await resources, we can guarantee that we will wait until the end of generating all the images from the canvas. This process may take some time depending on the size of your image.

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

Take a look at pdfMake github: https://github.com/bpampuch/pdfmake

And his playground with great examples and how to do it: http://pdfmake.org/playground.html

I'm still trying to update this method to solve this pagination problem, but it was the fastest way to solve this problem, and I hope to be useful to someone.

+1
source

Source: https://habr.com/ru/post/1245270/


All Articles