Requires installation
npm install html2canvas --save npm install jspdf --save
In order to avoid the truncation of PDF content or images, that is, some content is on the previous page and some content is on the next page, you must use code to process it.
1: First convert the height of the A4 paper (297mm) into the corresponding px unit value according to the screen resolution
2: Determine whether the current A4 page can accommodate the current sub-element. If it cannot, add a blank element to the current A4 page and squeeze the current element to the next page.
3: After processing the dom structure, execute printing
import html2canvas from 'html2canvas' import JsPDF from 'jspdf' /** * Export PDF * fileName: file name * htmlDom: htmlDom, through document.getElementById('') || document.querySelector('') * itemClassName: the common class name of the first child element in htmlDom */ export function exportPDF (fileName, htmlDom, itemClassName) { return new Promise((resolve, reject) => { //A4 size (mm), 210mm x 297mm const a4w = 197 const a4h = 297 // #########################################Get the A4 corresponding to the current screen Paper PX height######################################### //Convert A4 height to px of current screen resolution const inch = document.createElement('div') // Once you set the div's height to 1 inch, it will automatically scale based on the device's resolution inch.style.cssText = 'width:1in; height:1in; position:absolute; left:0px; top:0px; z-index:99; visibility:hidden;' document.body.appendChild(inch) const heightDpi = parseInt(inch.offsetHeight) document.body.removeChild(inch) //Convert millimeters to inches, and then to px (subtract 250px later, if the generated PDF still has gaps, increase this value) const a4PxHeight = Math.round(a4h / 25.4 * heightDpi * heightDpi / 72) - 250 // ####################Traverse each first-level sub-element and determine whether a blank sub-element is appended after it to prevent the element from appearing in two A4 papers# ############### if (itemClassName) { const childListID = htmlDom.getElementsByClassName(itemClassName) for (let i = 0; i < childListID.length; i + + ) { //The distance between the current element and the top of the page const offsetTop = childListID[i].offsetTop //Current element height const coffsetHeight = childListID[i].offsetHeight //Height + Distance from top / A4 paper px height const topHeightRate = (offsetTop + coffsetHeight) / a4PxHeight // If the current node is added, the A4 page cannot be displayed completely. if (topHeightRate > 1 & amp; & amp; topHeightRate % 1 !== 0) { // Distance from current element to top / px height of A4 paper const offsetTopRateStr = String(offsetTop / a4PxHeight) //The height of the current A4 page that is also occupied = offsetTopRateStr only retains decimal places * A4 paper px height const alreadyOccupyH = Math.round(Number('0' + offsetTopRateStr.substring(offsetTopRateStr.indexOf('.'))) * a4PxHeight) // If the current A4 page height occupies + current node height > A4 paper px height, add a blank node if ((alreadyOccupyH + coffsetHeight) > a4PxHeight) { // Get the parent node of the current node const divParent = childListID[i].parentNode const newNode = document.createElement('div') //Additional node height is: px height of A4 paper - the current page is occupied newNode.style.height = Math.round(a4PxHeight - alreadyOccupyH) + 'px' newNode.style.width = '100%' //Insert a blank node before the current element divParent.insertBefore(newNode, childListID[i]) } } } } // ############################################### Start exporting############################################## ######## html2canvas(htmlDom, { allowTaint: false, tainTest: false, logging: false, useCORS: true, dpi: 300, scale: 2 // Increase resolution proportionally }).then(canvas => { //A4 paper, portrait const pdf = new JsPDF('p', 'mm', 'a4') const ctx = canvas.getContext('2d') //Convert the pixel height of a page image according to the A4 display ratio const imgHeight = Math.floor(a4h * canvas.width / a4w) let renderedHeight = 0 while (renderedHeight < canvas.height) { const page = document.createElement('canvas') page.width = canvas.width //The content may be less than one page page.height = Math.min(imgHeight, canvas.height - renderedHeight) //Use getImageData to crop the specified area and draw it into the canvas object created previously page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0) //Add the image to the page, leaving 10mm margins pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'PNG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) renderedHeight + = imgHeight if (renderedHeight < canvas.height) { // If there is content later, add an empty page pdf.addPage() } //delete page } // save document pdf.save(fileName + '.pdf') resolve() }) }) }
For specific functions, introduce the above method, call it, and pass in the file name and htmlDom (html structure).
If the export is too blurry, increase the values of the parameters dpi and scale. However, the exported file may be larger accordingly. The basic principle is to convert the htmlDom into a picture and put it into a PDF, which may be a little bit larger. Vague.
Another thing that needs attention is that if there are Internet images in the htmlDom element, there will be no images when generating PDF, so you need to process them before generating PDF, convert all Internet images into base64 format, and then use the img tag src is the value of base64.
function imageToBase64 (url) { return new Promise((resolve, reject) => { const image = new Image() image.src = url + ' & amp;v=' + Math.random() // Handle caching image.crossOrigin = '*' // Support cross-domain images image.onload = () => { const canvas = document.createElement('canvas') canvas.width = image.width canvas.height = image.height const ctx = canvas.getContext('2d') ctx.drawImage(image, 0, 0, image.width, image.height) const base64 = canvas.toDataURL('image/png') resolve(base64) } }) }
Vue specifies the Html area to print, you can refer to my other article:vue print-js prints the HTML of a certain areahttp://t.csdnimg.cn/7IYta
Coding is not easy, it will be beneficial to you, don’t forget to like it
Don’t worry, you will have no friends in the future. No one in the world will know you.
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Vue entry skill treeHomepageOverview 39464 people are learning the system