技术栈: html2canvas + jspdf
简介
在实际业务开发中,经常需要实现将页面中的echarts图表和统计数据一键保存为pdf文件。
这涉及到两个阶段功能:
- 将页面某部分内容截取出来,成为图片格式(类似于截图)
- 将图片保存为pdf文件
于是,此处需要html2canvas.js 和 jspdf.js 两个插件。
jspdf官网: https://raw.githack.com/MrRio/jsPDF/master/docs/index.html
html2canvas官网: https://html2canvas.hertzen.com/
实现
安装
首次,需要安装此两个js插件
# npm
npm install html2canvas --save
npm install jspdf --save
# yarn
yarn add html2canvas
yarn add jspdf
js逻辑
插件安装好后,进行引入。
明确需要打印的元素、操作事件,接下来就是插件调用与逻辑处理了。
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
toBePdf(eleId) {
const theEle = document.getElementById(eleId); // 获取指定元素
// 将element绘制为canvas
html2Canvas(theEle).then(async (canvas) => {
let imgurl = canvas.toDataURL('image/png') // 将canvas转换为图片
let contentWidth = canvas.width
let contentHeight = canvas.height
// 将图片转为pdf格式(宽 > 高,则横向)
let pdf = new JsPDF(contentWidth > contentHeight ? 'l' : 'p', 'pt', [contentWidth, contentHeight])
pdf.addImage(imgurl, 'PNG', 0, 0, contentWidth, contentHeight)
pdf.save('document.pdf'); // 保存为pdf
}).error((err) => {
console.log(err)
})
}
应用
此处应用采用 Vue 的写法。
调用
<template>
<div>
<div id="toBeEle"> 3123123</div>
<button @click="toBePdf('toBeEle')">保存为pdf</button>
</div>
</template>
<style>
#toBeEle {
width: 100vw;
height: 20vh;
color: red;
}
</style>
效果
页面表现
pdf内表现
扩展
因个人实际工作业务中,还需要将报表内容以图片、pdf文件的形式通过邮件发送给指定客户,此处扩展发送邮件相关内容。实际是将邮件的内容发送给后端,由后端处理从而发送到邮箱。如需要纯前端实现,需要使用 email.js 插件并注册该系统的邮箱(发送包含附件的邮件需开通付费会员)。
sendEmail() {
const theEle = document.getElementById('toBePdf')
html2Canvas(theEle).then( async (canvas) => {
let imgurl = canvas.toDataURL('image/png')
let contentWidth = canvas.width
let contentHeight = canvas.height
let pdf = new JsPDF(contentWidth > contentHeight ? 'l' : 'p', 'pt', [contentWidth, contentHeight])
pdf.addImage(imgurl, 'PNG', 0, 0, contentWidth, contentHeight)
/**
* 邮件发送相关
*/
const formData = new FormData();
const title = '2023/09/20-2023/12/20 营收报表'
const imgTag = document.createElement('img');
imgTag.src = imgurl;
formData.append('to', this.model.email); // 收件人的电子邮件地址
formData.append('subject', title); // 邮件主题
formData.append('file', pdf.output('blob'), 'document.pdf'); // 添加PDF文件并转Blob格式(二进制数据对象)
formData.append('text', imgTag.outerHTML); // 邮件正文(这里是个图片)
// const text = '这是邮箱正文';
// formData.append('text', text);
await StatisticsAPI.sendEmail(formData); // 后端发送邮件的接口
})
}
// 接口请求配置
sendEmail: function sendEmail(param) {
return axios({
url: '/send-email',
method: 'post',
data: param,
headers: {
'Content-Type': 'multipart/form-data'
}
})
},
邮件效果
其他
关于html2canvas.js 和 jspdf.js 插件的具体描述,可以参考其他博客:
司徒小北 - jspdf用法
pingan8787 - 深度使用html2canvas的经验总结