简单的记录一下再vue中使用html2canvas结合jsPDF实现对页面转pdf功能的实现,主要是通过html2canvas将页面转化为高清的图片,后在进行导出pdf,话不多说,直接上代码
注意:如果使用的是uniapp的话,需要将div替换成view,以下代码可直接使用
第一步:通过npm安装html2canvas和jsPDF
npm install --save htmlcanvas2
npm install --save jspdf
第二步:则是在需要的页面引入后,通过$refs获取需要转成pdf容器的dom元素 ,通过html2canvas将页面转化为高清图片后在通过jsPDF导出为pdf文件(以下代码复制可直接使用)
<template>
<div>
<div @click="print" class="btn">转PDF</div>
<div ref="box" class="box">
<div class="item" v-for="item in data">{
{item.title}}</div>
</div>
</div>
</template>
<script>
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
export default {
data() {
return {
data: [{
title: '这是第一页',
}, {
title: '这是第二页',
}]
}
},
components: {
},
methods: {
async print() {
const el = this.$refs.box.$el
html2canvas(el, {
logging: false,
background: '#fff',
allowTaint: true,
taintTest: false,
height: el.scrollHeight,
width: el.scrollWidth,
useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
dpi: 300, // 提升导出的文件的分辨率
scale: 5
}).then(canvas => {
var canvasWidth = canvas.width; //图片容器宽度
var canvasHeight = canvas.height; //图片容器高度
let pagesHeight = '' //页面高度
let leftHeight = canvasHeight //未生成pdf的高度
var position = 0 //页面偏移
var imgWidth = 0
var imgHeight = 0
pagesHeight = canvasWidth / 592.28 * 841.89
imgWidth = 592.28;
imgHeight = 592.28 / canvasWidth * canvasHeight;
var pdf = new jsPDF('', 'pt', 'a4', true);
var pageData = canvas.toDataURL('image/jpeg', 1.0);
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pagesHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight, '', 'FAST')
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight, '',
'FAST')
leftHeight -= pagesHeight;
position -= 841.89;
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save('1')
//此处为保存到本地的pdf操作,如果需要上传到服务器的话,则在这个位置加入第三步代码替换pdf.save('1')
})
},
}
}
</script>
<style>
.btn {
height: 50px;
display: flex;
align-items: center;
justify-content: center;
background-color: palegreen;
}
.box {
background-color: paleturquoise;
font-size: 18px;
font-weight: 700;
width: 592px;
}
.box .item {
height: 841px;
}
</style>
第三步:以上代码只能简单的实现转pdf后下载到本地,如果需要实现通过后端接口上传到服务器的话, 则需要转base64后通过转文件流的形式调用后端接口上传到服务器
①将此处代码替换第二步中的pdf.save('1')
let base64 = pdf.output("datauristring")
let file = this.convertBase64ToFile(base64, '转pdf的文件名称')
②以下方法为将pdf转化为file文件流代码
// base64转文件
convertBase64ToFile(urlData, filename) {
var arr = urlData.split('base64,');
var type = arr[0].match(/:(.*?);/)[1];
var fileExt = type.split('/')[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename + "." + fileExt, {
type: type
});
},
第四步:可以结合element中的upLoad实现上传,以下实例为使用uniapp中的uni.uploadFile()实现文件的上传
①uniapp中的uni.uploadFile()实现文件的上传
uni.uploadFile({
url: 'xxxx', //上传地址
file: file, //文件对应第三步中的let file = this.convertBase64ToFile(base64, '转pdf的文件名称')
name: 'file',
formData: {
id: '123456',
}, //其他参数
success: () => {
} //成功后的回调
})
②其他上传实现可参考element组件或者原生请求方式(后续有时间再进行更新)