vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)
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 = 0
while (renderedHeight < canvas.height) {
var page = document.createElement('canvas')
page.width = canvas.width
page.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 += imgHeight
if (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
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25