刚好碰到这么一个需求,前端需要将后端返回的json对象数据生成表单样式的pdf文件,首次接触所以简单记录一下。
经过反复查找大致流程为:现在页面画一个表单=====>拿到数据将数据放表单中=====>给表单最外层加个ref利用html2Canvas生成base64图片=====>最后用jspdf将图片生成pdf。
先上个图:
首先安装依赖组件
npm install --save html2canvas // 页面转图片
npm install jspdf --save // 图片转pdf
然后将拿到的数据放入表单(表单大家都会吧,我就不往出贴了,放个图好了,主要看下ref的位置,一些其他的样式问题可根据自身需求调整)中
通过引用并调用html2canvas先生成base64图片
import html2canvas from 'html2canvas'
import jsPDF from "jspdf";
//点击事件 row是json对象数据,里面有要用的PDF文件名
AccountStatement(row) {
html2canvas(this.$refs.vueDomSaveToImage).then(res=>{ //图片生成
downloadPDF(res) //pdf生成 将图片生成后的json对象带过去,里面有要用到的参数
})
}
//调用jspdf方法
downloadPDF(canvas){
let contentWidth = canvas.width;
let contentHeight = canvas.height;
//一页pdf显示html页面的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
//未生成pdf的html页面高度
var leftHeight = contentHeight;
//页面偏移
var position = 0;
//a4纸的尺寸[595.28,841.89],生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0); //html2canvas生成的图片
// 第一个参数: l:横向 p:纵向
// 第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
var pdf = new jsPDF('p', 'pt', 'a4');
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
} else { //分页
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
// pdf.addImage(pageData,'JPEG', 25, position, imgWidth, Math.min(imgHeight, imgWidth * canvas.height / canvas.width));
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
//这里自己加参数判断一下
if(type==0){ //预览
pdf.output('dataurlnewwindow', "pdf名称.pdf"); //经过测试这里自定义名称无效并且在谷歌浏览器打开的预览页面下载按钮无效,火狐浏览器下载按钮可用
}else{
pdf.save( "pdf名称.pdf"); //导出
}
}
到这里功能上就基本搞定了,,只不过终究是截图转的pdf,可能会存在失真问题,可以在html2canvas截图时候加高一下精度跟倍数(不过倍数加到1.5以后在火狐就无效了,谷歌还行,加到2就比较清晰了)
还有其他的一些细节问题,比如分页截断问题暂时搞不定,,等有解决办法会重新发一下,,欢迎交流!!!