看了所有的博客都是用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文档才能同时明白
再说一遍,要一遍一遍又一遍,重要的事情说三遍,看文档!!!直到你看明白。