看了所有的博客都是用html2canvas
導出的,畫質都很模糊,它的原理是將你要導出的頁面放進一個dom
,然後利用這個插件把這個dom
轉換爲一張canvas
圖片,然後塞進pdf,到後導出,畫質模糊,但是它功能強大,能導出所有元素(圖片、文章等等)爲pdf。
我今天要說的是將頁面上已有的table
,或者後端返回的table數據
,導出爲pdf,包括上面所說的將頁面導出爲pdf,寫成了示例,這個是我的github示例地址,克隆項目到本地,按照下面的README.md
進行啓動,裏面註釋都很詳細,不明白可以私信,歡迎star。
我簡單說一下這個示例,就是將頁面上已有的table
,或者後端返回的table數據
,導出爲pdf,如下所示是將頁面上已有table導出 :
說一下實現過程,這說的是我的示例實現過程,有小夥伴要用的話,可以直接克隆我的項目,然後按照README.md
啓動就好:
下載依賴
import html2Canvas from 'html2canvas' // cnpm install --save html2canvas 這是將頁面dom都可以導出的,本身意思就是將html轉爲canvas圖片
import JsPDF from 'jspdf' // cnpm install jspdf --save
import 'jspdf-autotable' // cnpm install jspdf-autotable // 這是渲染pdf-table用到的, 下載完之後要修改源代碼,否則表頭還是中文亂碼,至於如何操作看github
html
因爲我兩種方法都寫了,所以在helloworld.vue
裏面寫上兩種方法,註釋已經很清晰了:
<template>
<div class="hello">
<!-- 這是第一種 -->
<button @click="getPdf('范德薩發的')">用html2canvans導出文件PDF</button>
<p>我的優點:可以導出任何東西,圖片或者文章或者表格,總之就是將你要導出的東西轉成一張圖片導出</p>
<p>我的缺點:導出畫質模糊</p>
<!-- 這是要導出的dom -->
<div id="pdfDom">
<table border="1">
<tr>
<td>第三方</td>
<td>虛線</td>
</tr>
<tr>
<td>是發v</td>
<td>程序</td>
</tr>
</table>
<img src="../assets/logo.png">
<div style="font-size: 20px;">
<p>哎呀呀呀</p>
<p>你瞅啥</p>
<p>瞅你咋地</p>
</div>
</div>
<p style="line-height: 180px;background: #ccc;color: #000;">------------------------------------------------------------------------------我是一條分割線--------------------------------------------------------------------------------------------------------</p>
<!-- 這是第二種 -->
<button @click="getPdfTable('tableDom' ,'吃的飯')">用autotable導出表格文件pdf</button>
<p>我的優點:可以導出頁面上的table,或者後臺動態返回的table數據,畫質清晰</p>
<p>我的缺點:只能導出table</p>
<!-- 這是要預覽pdf的地方 -->
<iframe id="tableDom" width="100%" height="500px">
</iframe>
<div>
<!-- 這是要導出的頁面上的table -->
<table id="basic-table" border="2">
<tr>
<td>芙蓉</td>
<td>方如果他不</td>
<td>大V發的</td>
</tr>
<tr>
<td>個人個投入</td>
<td>不放過會讓你</td>
<td>存放的</td>
</tr>
<tr>
<td>如果他人吧</td>
<td>虧空</td>
<td>輔導班</td>
</tr>
</table>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App',
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello >p{
color: red;
}
#pdfDom{
width: 100%;
border: 1px solid;
}
</style>
獲取中文字體
這個不詳細說了,在項目下static文件夾
下新建一個font文件夾
,放進去一個font.js文件
,這個js文件裏面放你獲取的中文字體文件base64
,具體怎麼獲取看這篇博文講得很清楚了
寫導出方法
依賴已經下載了,然後在項目src文件夾下新建一個文件夾until
,放這個方法的htmlToPdf.js
文件,註釋都寫全了:
import html2Canvas from 'html2canvas' // cnpm install --save html2canvas
import JsPDF from 'jspdf' // cnpm install jspdf --save
import 'jspdf-autotable' // cnpm install jspdf-autotable // 下載完之後要修改源代碼,否則表頭還是中文亂碼
import moo from '../../static/font/font' // 中文字體文件
export default{
install (Vue, options) {
// ====第一種--使用html2canvas導出pdf=============================================================================================================
Vue.prototype.getPdf = function (titles) {
var title = titles
html2Canvas(document.querySelector('#pdfDom'), { // 導出的dom可以傳參
allowTaint: true
}).then(function (canvas) {
let contentWidth = canvas.width
let contentHeight = canvas.height
let pageHeight = contentWidth / 592.28 * 841.89
let leftHeight = contentHeight
let position = 0
let imgWidth = 595.28
let imgHeight = 592.28 / contentWidth * contentHeight
let pageData = canvas.toDataURL('image/jpeg', 1.0)
let PDF = new JsPDF('', 'pt', 'a4')
PDF.setFontSize(22); // 因爲畫質模糊,所以這裏字體設置大一些,就清晰了
// pageData
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')
}
)
},
// =======第二種 --使用動態數據、或者頁面數據導出pdf表格==============================================================================================
Vue.prototype.getPdfTable = function (dom ,titles) {
var doc = new JsPDF('p', 'pt'); // 獲取實例
var res = doc.autoTableHtmlToJson(document.getElementById("basic-table")); // 這是獲取頁面已有table的數據導出 ,順序不能亂放,要不就會亂碼,獲取的basic-table可以傳參
// =============================== 設置字體
doc.addFileToVFS('pingfang.ttf', moo)
doc.addFont('pingfang.ttf', 'b', 'normal');
doc.setFont('b');
// ===============================
// doc.autoTable({ // 這是動態獲取後臺table數據數據導出,如果用這個,則註釋掉 46行、69-79行即可
// styles: { fillColor: [0, 0, 0], font: 'b', textColor: [255,255,255] },
// theme: 'grid',
// body: [ // 可以傳參
// { europe: '大幅度', america: '更豐富', asia: '防輻射' },
// { europe: 'Norway', america: 'Mexico', asia: 'Japan' },
// ],
// columns: [ // 可以傳參
// { header: '表頭1', dataKey: 'europe' },
// { header: '表頭2', dataKey: 'asia' },
// { header: '表頭3', dataKey: 'america' },
// ],
// })
doc.autoTable({ // 這是獲取頁面已有table的數據導出 ,順序不能亂放,要不就會亂碼
styles: { fillColor: [0, 0, 0], font: 'b', textColor: [255,255,255] , halign: 'center',}, // 樣式
theme: 'grid', // 主題
startY: 100, // 距離上邊距離
body: res.data, // tableDate
columns: [ // 表頭// 可以傳參
{ header: '表頭1', dataKey: 'europe' },
{ header: '表頭2', dataKey: 'asia' },
{ header: '表頭3', dataKey: 'america' },
],
})
doc.text(40, 30, '個人號還挺好') // 渲染title // 可以傳參
document.getElementById(dom).src = doc.output('datauristring'); // 渲染pdf
doc.save("table.pdf"); // 導出pdf // 名字可以傳參
}
}
}
全局掛載
方法寫好了以後,在全局使用:
// main.js
import htmlToPdf from '@/untils/htmlToPdf'
Vue.use(htmlToPdf
到這就完了,其實過程中還是要一遍遍看官方的github,畢竟這是歪果仁寫的,也沒有什麼中文文檔,全英文介紹,而且示例還要找來找去,再一個就是他這個依賴衆多,你要看好幾個依賴的github文檔才能同時明白
再說一遍,要一遍一遍又一遍,重要的事情說三遍,看文檔!!!直到你看明白。