1. First install the html2canvas and jspdf plug-ins
2. Create a new html2pdf.js file and place it in the util folder to edit the code.
There are a lot of codes using html2canvas and jspdf plug-ins on the Internet. When exporting, sometimes the exported content has scroll bars. If the exported content is incomplete, only the visible part can be exported. The content hidden by the scroll bar will not be displayed. Personally I spent half a day researching and solved this problem.
The key code is as follows:
1. Set the height/width of the element to the scroll height before exporting, such as:
2. After converting to an image, set the height/width back.
The test results can be exported to the complete page including the part hidden by the scroll bar. The following is the complete code.
import jsPDF from 'jspdf' import html2canvas from 'html2canvas' /* * Instructions for use * ele: The container element that needs to be exported to pdf (dom node not id) * pdfFileName: The name of the exported file can also be changed by passing parameters by calling the outPutPdfFn method. * splitClassName: Class name to avoid segmentation truncation. This parameter needs to be passed in when the pdf has multiple pages, to avoid truncation of elements when the pdf is divided into pages, such as tables <tr class="itemClass"></tr> * Calling method first let pdf = new PdfLoader(ele, 'pdf' ,'itemClass'); * If you want to change the pdf name pdf.outPutPdfFn(fileName); the outPutPdfFn method returns a promise and you can use the then method to process the logic after pdf generation. * */ class PdfLoader { constructor(ele, pdfFileName, splitClassName) { this.ele = ele this.pdfFileName = pdfFileName this.splitClassName = splitClassName this.A4_WIDTH = 841.89 this.A4_HEIGHT = 595.28 } async getPDF(resolve) { const ele = this.ele const pdfFileName = this.pdfFileName const eleW = ele.offsetWidth // Get the width of the container const eleH = ele.scrollHeight // Get the height of the container const eleOffsetTop = ele.offsetTop // Get the distance from the container to the top of the document const eleOffsetLeft = ele.offsetLeft // Get the distance from the container to the far left of the document window.pageYoffset = 0 document.documentElement.scrollTop = 0 document.body.scrollTop = 0 const canvas = document.createElement('canvas') let abs = 0 const win_in = document.documentElement.clientWidth || document.body.clientWidth // Get the width of the current visual window (excluding scroll bars) const win_out = window.innerWidth // Get the width of the current window (including scroll bars) if (win_out > win_in) { abs = (win_out - win_in) / 2 // Get half the width of the scroll bar } canvas.width = eleW * 2 // Double the canvas width & amp; & amp; height canvas.height = eleH * 2 const context = canvas.getContext('2d') context.scale(2, 2) //Enhance picture clarity context.translate(-eleOffsetLeft - abs, -eleOffsetTop) ele.style.height = ele.scrollHeight + 'px' // Get the scroll height of the element, used to intercept the part hidden by the scroll bar html2canvas(ele, { backgroundColor: null, allowTaint: false, dpi: window.devicePixelRatio * 4, width: ele.width, height:ele.width, windowWidth: ele.scrollWidth, scale: 4, // Increase resolution proportionally useCORS: true, // Allow cross-domain requests for external link images in the canvas canvas, and allow cross-domain requests. }).then(async (canvas) => { const contentWidth = canvas.width const contentHeight = canvas.height ele.style.height = ele.clientHeight + 'px' // Get the actual height of the element, excluding the hidden part of the scroll bar // One page of pdf displays the canvas height generated by the html page; const pageHeight = (contentWidth / this.A4_WIDTH) * this.A4_HEIGHT // The purpose of writing this is to keep the width and height ratio consistent pageHeight/canvas.width = a4 paper height/a4 paper width // The width is consistent with canvas.width //The html page height of the pdf is not generated let leftHeight = contentHeight // page offset let position = 0 //The size of a4 paper [595,842], unit pixel, the width and height of the canvas generated by the html page in the pdf image const imgWidth = this.A4_WIDTH - 10 // -10 for the right margin of the page const imgHeight = (this.A4_WIDTH / contentWidth) * contentHeight const pageData = canvas.toDataURL('image/jpeg', 1.0) const pdf = jsPDF('l', 'pt', 'a4') // There are two heights that need to be distinguished, one is the actual height of the html page, and the page height of the generated pdf (841.89) // When the content does not exceed the range displayed on one PDF page, no paging is required if (leftHeight < pageHeight) { // Set in pdf.addImage(pageData, 'JPEG', left, top, width, height) to display in pdf; pdf.addImage(pageData, 'JPEG', 5, 0, imgWidth, imgHeight) // pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight); } else { // paging while (leftHeight > 0) { pdf.addImage( pageData, 'JPEG', 5, position, imgWidth, imgHeight ) leftHeight -= pageHeight position -= this.A4_HEIGHT // Avoid adding blank pages if (leftHeight > 0) { pdf.addPage() } } } pdf.save(pdfFileName + '.pdf', { returnPromise: true }).then(() => { // Remove the added empty div to prevent page clutter const doms = document.querySelectorAll('.emptyDiv') for (let i = 0; i < doms.length; i + + ) { doms[i].remove() } }) this.ele.style.height = '' resolve() }) } //This method is to prevent content (such as charts) from being truncated due to A4 paper problems async outPutPdfFn(pdfFileName) { return new Promise((resolve, reject) => { this.ele.style.height = 'initial' pdfFileName ? (this.pdfFileName = pdfFileName) : null const target = this.ele const pageHeight = (target.scrollWidth / this.A4_WIDTH) * this.A4_HEIGHT // Get the split dom, here is the dom with the class name item const domList = document.getElementsByClassName(this.splitClassName) // Perform splitting operation. When the dom content exceeds the height of a4, insert an empty dom in front of the dom, squeeze it down, and split it. let pageNum = 1 // pdf page number const eleBounding = this.ele.getBoundingClientRect() for (let i = 0; i < domList.length; i + + ) { const node = domList[i] const bound = node.getBoundingClientRect() const offset2Ele = bound.top - eleBounding.top const currentPage = Math.ceil( (bound.bottom - eleBounding.top) / pageHeight ) // Which page the current element should be on if (pageNum < currentPage) { pageNum++ const divParent = domList[i].parentNode // Get the parent node of the div const newNode = document.createElement('div') newNode.className = 'emptyDiv' newNode.style.background = 'white' newNode.style.height = pageHeight * (pageNum - 1) - offset2Ele + 30 + 'px' // + 30 to have a top margin when changing to the next page newNode.style.width = '100%' divParent.insertBefore(newNode, node) //Insert an empty new node in front of each node to prevent the content from being split and truncated. } } // Asynchronous function, handles interaction after successful export this.getPDF(resolve, reject) }) } } export default PdfLoader
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Vue entry skill tree Home page Overview 39487 people are learning the system