1、使用html2canvas和jspdf插件实现
该方式是通过html2canvas将HTML页面转换成图片,然后再通过jspdf将图片的base64生成为pdf文件。
实现步骤如下:
(1)下载插件模块:
npm install html2canvas jspdf --save
npm install jspdf --save
(2)定义功能实现方法
在项目工具方法存放文件夹utils中创建htmlToPdf.js文件,
代码如下:
export default{
install (Vue, options) {
Vue.prototype.getPdf = function () {
// console.log('begin download...')
setTimeout(( =>{
//console.log('downloading...')
var title = this.htmlTitle
html2canvas($("#pdfDom")[0],{
**配置参数**
width: 980,
height: 980 * 1.4142 * this.page,
background: "#fff",
scale: 2.1,
tainttest: true,
logging: false,
letterRendering: true,
llowTaint: true
}).then(function (canvas) {
var contentWidth = canvas.width
var contentHeight = canvas.height
// A4纸宽高
var A4Width = 595.28
var A4Height = 841.89
// 一页pdf显示html页面生成的canvas高度
var pageHeight = contentWidth / A4Width * A4Height
// 未生成pdf的html页面高度
var leftHeight = contentHeight
// pdf页面偏移
var position = 0
// pdf页面内边距
var pdfPadding = 0
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = A4Width
var imgHeight = A4Width / contentWidth * contentHeight
var pageData = canvas.toDataURL('image/jpeg', 1.0)
var pdf = new JsPdf('', 'pt', 'a4')
// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', pdfPadding, 0, imgWidth, imgHeight)
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', pdfPadding, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= A4Height
leftHeight > 0 && pdf.addPage()
}
}
PDF.save(title + '.pdf')
}
}
},2000)
}
}
}
(3)全局引入实现方法
在项目主文件main.js中引入定义好的实现方法,并注册。
import htmlToPdf from '@/components/utils/htmlToPdf'
// 使用Vue.use()方法就会调用工具方法中的install方法
Vue.use(htmlToPdf)
(4)在相关要导出的页面中,点击时调用绑定在Vue原型上的getPdf方法,传入id即可
//html
<div id="pdfDom">
//要下载的HTML页面,页面是由后台返回
<div v-html="pageData"></div>
</div>
<el-button type="primary" size="small" @click="getPdf('#pdfDom')">点击下载</el-button>
原理差不多,只不过下边的方法更好些,下载的pdf页面多的情况也可以下载出来,用上边的方法,内容多的情况,下载会出现空白页的情况,下边的方法我认为是好于上边的。下边的方法我是通过iframe来实现的
2、使用dom-to-image和jspdf插件实现
实现步骤如下:
(1)下载插件模块:
npm install dom-to-image --save
npm install jspdf --save
(2、3、4) 同上
为避免下载的不全或者后台数据还没加载完全,就下载pdf ,所以最好在mounted里 通过eventBus,执行完获取数据的方法之后加一个延时器,确保后台返回的数据都已经渲染完,再执行下载的方法,
async mounted() {
await this.getData();
this.$nextTick(() => {
setTimeout(() => {
this.$Eventbus.$emit("isCanDownload", { isRendered: true });
}, 1000);
});
},
在预览页的mounted里接收一下,判断条件加好,条件成立,再执行下载的方法
this.$Eventbus.$on("isCanDownload", (val) => {
if (val.isRendered && this.isDownload) {
this.isDownload = false;
this.download();
}
});
window.addEventListener(
"message",
(event) => {
if (event.data === "下载") {
this.isDownload = true;
}
},
false
);
在主页面可以这样来写,代码如下
<div class="custom-pdf" v-if="href">
<iframe
:src="href"
frameborder="0"
id="custom-pdf"
></iframe>
</div>
然后在下载的方法同上getpdf里边调用方法
this.$nextTick(() => {
document.getElementById("custom-pdf").onload = () => {
document
.getElementById("custom-pdf")
.contentWindow.postMessage(
"下载",
location.origin + "/" + router.href
);
};
window.addEventListener(
"message",
(event) => {
if (event.data === "完成") {
this.isDownloading = false;
}
},
false
);
});