前端實現Vue項目導出PDF

方式一:使用html2canvas和jspdf插件實現

該方式是通過html2canvas將HTML頁面轉換成圖片,然後再通過jspdf將圖片的base64生成爲pdf文件。

缺點:

  • 生成的pdf質量不高,失真比較嚴重;
  • 在分頁處如果有圖片的話,不會自動識別隔頁處理(甚至一行文字也能給你上下一分爲二),而是無情地把圖片一分爲二。

實現步驟如下:
1.安裝插件 jspdf html2canvas

    第一個.將頁面html轉換成圖片
    npm install --save html2canvas 
    第二個.將圖片生成pdf
    npm install jspdf --save

2、定義全局函數…創建一個htmlToPdf.js文件在指定位置。個人習慣放在(‘src/scripts/common/utils/htmlToPdf’)'

分頁處理:

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.getPdf = function (idStr, title) {
      html2Canvas(document.querySelector('#' + idStr), {
        // allowTaint: true,
        useCORS: true,
        // scale: 2, // 提升畫面質量,但是會增加文件大小
      }).then((canvas) => {
        const contentWidth = canvas.width
        const contentHeight = canvas.height
        // 一頁pdf顯示html頁面生成的canvas高度;
        const pageHeight = contentWidth / 592.28 * 841.89
        // 生成pdf的html頁面高度
        let leftHeight = contentHeight
        // 頁面偏移
        let position = 0
        // a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
        const imgWidth = 595.28
        const imgHeight = 592.28 / contentWidth * contentHeight
        // canvas.crossOrigin="anonymous";
        const pageData = canvas.toDataURL('image/jpeg', 1.0)

        const PDF = new JsPDF('', 'pt', 'a4')
        // 有兩個高度需要區分,一個是html頁面的實際高度,和生成pdf的頁面高度(841.89)
        // 當內容未超過pdf一頁顯示的範圍,無需分頁
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            if (leftHeight > 0) {
              // 避免添加空白頁
              PDF.addPage()
            }
          }
        }       
        PDF.save(title + '.pdf')
      })
    }
  },
}

不分頁處理:

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.getPdf = function (idStr, title) {
      html2Canvas(document.querySelector('#' + idStr), {
        // allowTaint: true,
        useCORS: true,
        // scale: 2, // 提升畫面質量,但是會增加文件大小
      }).then((canvas) => {
        const contentWidth = canvas.width
        const contentHeight = canvas.height
         
         /* 導出不分頁處理 */
        const pageData = canvas.toDataURL('image/jpeg', 1.0)

        const pdfWidth = (contentWidth + 10) / 2 * 0.75
        const pdfHeight = (contentHeight + 200) / 2 * 0.75 // 500爲底部留白

        const imgWidth = pdfWidth
        const imgHeight = (contentHeight / 2 * 0.75) // 內容圖片這裏不需要留白的距離

        const PDF = new JsPDF('', 'pt', [ pdfWidth, pdfHeight, ])
        PDF.addImage(pageData, 'jpeg', 0, 0, imgWidth, imgHeight)
        PDF.save(title + '.pdf')
      })
    }
  },
}

3, 全局引入實現方法
在項目主文件中引入定義好的實現方法,並註冊

import htmlToPdf from '@/scripts/common/utils/htmlToPdf'
// 使用Vue.use()方法就會調用工具方法中的install方法
Vue.use(htmlToPdf)

4, 在相關要導出的頁面中,點擊時調用綁定在Vue原型上的getPdf方法,傳入id即可

<div id="pdfDom">
	//給自己需要導出的ui部分.定義id爲"pdfDom".此部分將就是pdf顯示的部分
</div>
<el-button @click="export">導出PDF</el-button>
export default {
	data () {
		return {
			fileName: '頁面導出PDF文件名'
		}
	}
	methods:{
		export () {
			this.getPdf('pdfDom', this.fileName)
		}
	} 
 }

問題:

  • 分頁:jspdf需要使用高度較小的圖片,圖片高度越小,分頁效果就越好。

  • pdf清晰度:如果利用了echart之類,一定要用它給的api獲取dataURL,設置分辨率倍數多一點,導出的圖片非常清晰,這樣生產的pdf纔會清晰。如果是普通元素,如果發現導出的圖片不夠清晰,可以專門寫一個用於導出的頁面。此頁面所有內容都放大2 倍,然後設置left:-9999隱藏(不可display:none)。當html2canvas轉換此頁面的爲圖片的時候,圖片會非常大,然後使用pdf編輯工具讓圖片等比縮放,會很清晰。html2canvas option裏也有個scale參數,也可以調,但太大會報錯。

方式二:調用瀏覽器自身的方法。

window.print() 來打印(打印時可選下載),打印比較清晰,但存在瀏覽器兼容問題,適用於谷歌。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章