vue导出pdf
需求:需要前端下载把当前html下载成pdf文件–有十八页超长,之前使用vue-html2pdf组件,但是这个组件有长度限制和比较新浏览器版本限制,所以改成使用html2canvas和jspdf组件
方法:
1、第一步:我们要添加两个模块
//第一个:将页面html转换成图片
npm install --save html2canvas
//第二个:将图片生成pdf
npm install jspdf --save
2、第二步:在.vue界面编写,例如我的页面叫BusinessAnalysis.vue,必须在你想要下载的父级加一个id,例如我下面代码 id=“html2PdfId”
<template>
<div ref="ananysisPageRef" class="business-analysis-wrap" >
<div id="html2PdfId">
//=====这里是你自己写的想转成pdf的代码
</div>
<a-button
type="primary"
:loading="exportLoading"
@click="handleExportAI2()"
>
导出PDF
</a-button>
</div>
</template>
<script>
import VueHtml2pdf from 'vue-html2pdf'
import html2canvas from 'html2canvas'
export default {
name: 'BusinessAnalysis',
data() {
return {
pdfOptions: {
pageWidth: 594, // A2横向宽度(mm)
pageHeight: 420, // A2横向高度(mm)
imageQuality: 0.8,
},
exportLoading: false,
pdfBase64: '',
base64Images: [],
}
}
methods: {
handleExportAI2() {
this.$message.loading({ content: '导出PDF文件中...', key: 'exportPagePdfLoading' })
this.exportLoading = true
this.generatePDF() // 生产pdf base64 --物业经营分析2
},
async generatePDF() {
const startTime = performance.now()
try {
await this.$nextTick()
// 1. 定义要截图的元素ID(按顺序)
// 2. 截图所有元素并计算高度
const elements = await this.captureComponents1()
console.log('elements', elements)
const img = await this.loadImage(elements[0])
// this.restoreAfterCapture();
// 3. 创建PDF并智能分页
const pdf = new JsPDF({
orientation: 'l',
unit: 'mm',
format: [this.pdfOptions.pageWidth, this.pdfOptions.pageHeight],
// format: 'a4',
// compress: true
})
// 计算分页参数:ml-citation{ref="6,8" data="citationList"}
const imgRatio = img.width / img.height
const scaledWidth = this.pdfOptions.pageWidth
const scaledHeight = scaledWidth / imgRatio
const totalPages = Math.ceil(scaledHeight / this.pdfOptions.pageHeight)
// 分页渲染:ml-citation{ref="5,8" data="citationList"}
for (let i = 0; i < totalPages; i++) {
if (i > 0) pdf.addPage()
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// 计算截取区域:ml-citation{ref="6,8" data="citationList"}
const sliceHeight = (img.height * this.pdfOptions.pageHeight) / scaledHeight
const startY = i * sliceHeight
const isLastPage = i === totalPages - 1
const currentSliceHeight = isLastPage ? img.height - startY : sliceHeight
// 设置画布尺寸:ml-citation{ref="3,5" data="citationList"}
canvas.width = img.width
canvas.height = currentSliceHeight
// 绘制图片分段:ml-citation{ref="5,6" data="citationList"}
ctx.drawImage(
img,
0,
startY, // 源坐标
img.width,
currentSliceHeight, // 源尺寸
0,
0, // 目标坐标
canvas.width,
canvas.height // 目标尺寸
)
// 计算PDF中的显示高度:ml-citation{ref="6,8" data="citationList"}
const displayHeight = isLastPage
? (currentSliceHeight * this.pdfOptions.pageWidth) / img.width
: this.pdfOptions.pageHeight
pdf.addImage(canvas, 'JPEG', 0, 0, this.pdfOptions.pageWidth, displayHeight, undefined, 'FAST')
canvas.width = 1
canvas.height = 1
}
this.exportLoading = false
this.$message.success({ content: '导出成功!', key: 'exportPagePdfLoading', duration: 1 })
pdf.save('物业经营小项目分享.pdf')
} catch (error) {
console.error('生成PDF失败:', error)
alert('生成PDF失败: ' + error.message)
} finally {
this.isGenerating = false
}
},
loadImage(base64) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve(img)
img.onerror = reject
img.src = base64
})
},
async captureComponents1() {
// 确保DOM更新完成(针对Vue的动态渲染)
await this.$nextTick()
const elements = [document.getElementById('html2PdfId')]
const base64Images = []
// 顺序截图(避免并行导致内存溢出)
for (const element of elements) {
// 分块截图
try {
const canvas = await html2canvas(element, {
useCORS: true, // 允许跨域资源
logging: false, // 关闭日志
backgroundColor: '#FFFFFF', // 设置纯白背景
scale: 2, // 提高分辨率(2倍)
allowTaint: true, // 禁止污染画布
removeContainer: true, // 自动移除临时容器
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight,
// ignoreElements: (el) => {
// // 过滤不需要渲染的元素
// if (
// el.contains(element) ||
// element.contains(el) ||
// el.tagName === 'STYLE' ||
// el.tagName === 'LINK' ||
// // el.tagName === 'IMG' ||
// el.getAttribute('data-html2canvas') != null // header里面的样式不能筛掉
// ) {
// // console.log(el);
// return false
// }
// // console.log(e.tagName);
// return true
// },
// dpi: 300
})
const dataUrl = canvas.toDataURL('image/png', 1.0)
base64Images.push(dataUrl)
} catch (error) {
console.error('截图失败:', element, error)
base64Images.push('') // 空值占位
}
}
return base64Images
},
}
}
</script>
上面基本上是完整的代码,花了九头二虎之力,就是还是会出现截断的情况,我没办法解决,如果有大佬,求大佬指导
可以下载22页呢,就是下载的时候先截图成图片,再转为pdf很慢,如果有大佬能解决很慢的问题,求指导