方式一:使用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() 來打印(打印時可選下載),打印比較清晰,但存在瀏覽器兼容問題,適用於谷歌。