vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)
- 1、安装依赖
- 2、在utils中创建htmlToPDF.js文件
- 3、在vue中引入并使用
1、安装依赖
npm install --save html2canvas
npm install jspdf --save
2、在utils中创建htmlToPDF.js文件
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
var noTableHeight = 0 export const htmlPdf = (title, html, fileList, type) => {if (fileList) {const pageHeight = Math.floor(277 * html.scrollWidth / 190) + 20 for (let i = 0; i < fileList.length; i++) { const multiple = Math.ceil((fileList[i].offsetTop + fileList[i].offsetHeight) / pageHeight) if (isSplit(fileList, i, multiple * pageHeight)) { var _H = '' if (fileList[i].localName !== 'tr') { _H = multiple * pageHeight - (fileList[i].offsetTop + fileList[i].offsetHeight)} else {_H = multiple * pageHeight - (fileList[i].offsetTop + fileList[i].offsetHeight + noTableHeight) + 20}var newNode = getFooterElement(_H) const divParent = fileList[i].parentNode const next = fileList[i].nextSibling if (next) {divParent.insertBefore(newNode, next)} else {divParent.appendChild(newNode)}}}}html2Canvas(html, {allowTaint: false,taintTest: false,logging: false,useCORS: true,dpi: window.devicePixelRatio * 1,scale: 1 }).then(canvas => {var pdf = new JsPDF('p', 'mm', 'a4') var ctx = canvas.getContext('2d')var a4w = type ? 277 : 190; var a4h = type ? 190 : 277 var imgHeight = Math.floor(a4h * canvas.width / a4w) var renderedHeight = 0while (renderedHeight < canvas.height) {var page = document.createElement('canvas')page.width = canvas.widthpage.height = Math.min(imgHeight, canvas.height - renderedHeight)page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) renderedHeight += imgHeightif (renderedHeight < canvas.height) {pdf.addPage()}}pdf.save(title + '.pdf')})
}
const getFooterElement = (remainingHeight, fillingHeight = 0) => {const newNode = document.createElement('div')newNode.style.background = '#ffffff'newNode.style.width = 'calc(100% + 8px)'newNode.style.marginLeft = '-4px'newNode.style.marginBottom = '0px'newNode.classList.add('divRemove')newNode.style.height = (remainingHeight + fillingHeight) + 'px'return newNode
}
const isSplit = (nodes, index, pageHeight) => {if (nodes[index].localName !== 'tr') { noTableHeight += nodes[index].clientHeight}if (nodes[index].localName !== 'tr') {return nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight} else {return nodes[index].offsetTop + nodes[index].offsetHeight + noTableHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight + noTableHeight > pageHeight}
}
3、在vue中引入并使用
<template><div><button class="primary-btn" @click="handleExport">导出</button><div class="check-wrapper" id="pdfRef"><div class="page1-box pdfRef">11</div><div class="page2-box pdfRef">11</div><div class="page3-box pdfRef">11</div><div class="page4-box pdfRef">11</div><div class="page5-box pdfRef">11</div><div class="page6-box pdfRef">11</div><div class="page7-box pdfRef">11</div><div class="page8-box pdfRef">11</div></div></div>
</template>
<script setup>import { htmlPdf } from "@/utils/htmlToPDF.js" const handleExport = (name) => {var fileName= '投资评审报告'const fileList = document.getElementsByClassName('pdfRef') htmlPdf(fileName, document.querySelector('#pdfRef'), fileList)}
</script>