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-buttontype="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 = truethis.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.heightconst scaledWidth = this.pdfOptions.pageWidthconst scaledHeight = scaledWidth / imgRatioconst 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) / scaledHeightconst startY = i * sliceHeightconst isLastPage = i === totalPages - 1const currentSliceHeight = isLastPage ? img.height - startY : sliceHeight// 設置畫布尺寸:ml-citation{ref="3,5" data="citationList"}canvas.width = img.widthcanvas.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.pageHeightpdf.addImage(canvas, 'JPEG', 0, 0, this.pdfOptions.pageWidth, displayHeight, undefined, 'FAST')canvas.width = 1canvas.height = 1}this.exportLoading = falsethis.$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 = rejectimg.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很慢,如果有大佬能解決很慢的問題,求指導