vue2利用html2canvas+jspdf动态生成多页PDF方式
作者:流情
利用vue2结合html2canvas和jspdf,可以实现前端页面内容导出为PDF的功能,首先需要安装相关依赖,使用html2canvas将指定div内容捕捉为图像,再通过jspdf将图像转换为PDF
vue2用html2canvas+jspdf动态生成多页PDF
业务需求中,前端把页面上的内容导出为图片,pdf,excel是常有的事。
当然,这些工作后端也是能做。秉着前端是万能的理念,今天就站在前端的角度上,来实现将页面内容导出为pdf,实现指定div内容导出,并自动拼接成一个多页的PDF文件
1.PDF相关依赖
vue2脚手架项目中,关于PDF的依赖老生常用的就那么几个。
pdfmake,vue-print-nb,v-html5-renderer,print-js,html2pdf.js,vue-pdf。
总结起来无非就是达到将内容生成pdf,预览pdf这两个业务场景。
本篇讲的是通过html2canvas+jspdf来动态指定div内容转化为pdf
html2canvas
可以将 HTML 画布(canvas)捕捉为图像,然后 jspdf
可以将这些图像转换为 PDF 格式
第一步先安装依赖
npm install jspdf html2canvas --save # 或者 yarn add jspdf html2canvas
2.效果展示及源码
导出后一个div为一个pdf页面,不足的留空白。超出的会自动加页面补充。
假设,你首页想指定一个图片作为封面,中间的一大段内容从第二页开始,自动往后分页。那就设置两个div就行了。
PDF生成后的大致效果:
下面附上代码,就一个vue文件,方便各位拿来即用,能立马看到效果:
<template> <div id="pdfinsurancepdf"> <div style="width: 490pt;margin: auto;"> <div class="title" style="padding:20pt"> <el-button type="primary" @click="downpdf">下载PDF</el-button> <el-divider></el-divider> </div> <div id="page1"> <img src="@/assets/1.jpg" style="width:100%;height:auto" alt="封面" /> </div> <div id="page2"> <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </template> <div> <pre> 当你在凝视着网页的时候 网页也正在凝视着你 流情|导航站 Who is liuqing? 种一棵树最好的时间是十年前,然后就是现在——致想做还未来得及做的你 How lucky to meet you! 你好,这里是流情 Liuqing ,26岁,技术宅,对有趣的世界和可能有趣的你感到好奇,热爱IT和国风文化, 从事互联网产品/Web开发相关工作。希望能与你在比特之海的繁星之下相见! </pre> </div> </div> <div id="page3"> <div> <img src="@/assets/2.jpg" style="width:100%;height:auto" alt="结束页" /> </div> </div> </div> </div> </template>
<script> import html2canvas from 'html2canvas'; import JsPDF from 'jspdf'; export default { name:'insurancepdf', data() { return { compony:"pdf导出多页测试", tableData: [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1517 弄' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1519 弄' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1516 弄' }] } }, moutned() { console.log(123) }, methods:{ downpdf(){ const pdf = new JsPDF('p', 'mm', 'a4'); var divIds = ['page1', 'page2','page3']; const promises = divIds.map(divId => { const div = document.getElementById(divId); return html2canvas(div, { allowTaint: false, taintTest: false, logging: false, useCORS: true, dpi: window.devicePixelRatio * 1, scale: 2 //画布分辨率 }); }); Promise.all(promises).then(canvases => { canvases.forEach((canvas, index) => { if (index > 0) { pdf.addPage(); } this.addCanvasToPdf(pdf, canvas); }); pdf.save('pdf导出多页测试.pdf'); }).catch(error => { console.error('Error generating PDF:', error); }); }, addCanvasToPdf(pdf,canvas){ // 接下来使用canvas创建PDF var ctx = canvas.getContext('2d'); var a4w = 190; var a4h = 277; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277 var imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4显示比例换算一页图像的像素高度 var renderedHeight = 0; while (renderedHeight < canvas.height) { var page = document.createElement('canvas'); page.width = canvas.width; page.height = Math.min(imgHeight, canvas.height - renderedHeight);// 可能内容不足一页 // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中 page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0); pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加图像到页面,保留10mm边距 renderedHeight += imgHeight; if (renderedHeight < canvas.height) { pdf.addPage();// 如果后面还有内容,添加一个空页 } // delete page; } } } } </script>
<style scoped> #pdfinsurancepdf{ width: 100%; background: #fff; } span{ line-height: 30pt; } </style>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。