第一步 在utils下面创建一个工具文件exportPDF.js

以下每一句代码都有对应的注释,并且针对不同情况,作出了相应的解释,如果有需要的话,请耐心看完。

import html2Canvas from 'html2canvas';
import JsPDF from "jspdf";
/*** [获取页面导出的pdf文件]* @param   {[Object]}  options  [导出pdf配置项,包括一个title属性设置文件名,以及query属性设置获取元素的条件]*/
function exportPDF(options) {var title = options.title || '标题';// 导出文件名,默认为“标题”// 这里获取调用这个方法传过来的参数对象里面的类名,也就是你需要导出为pdf元素的父盒子类名const ele = document.getElementsByClassName(options.className || "pdf-cell");// 这里面我要解释一下,这里是要为做分页做准备,因为分页是根据每一个dom元素的高度来决定的,也不用细化到每一个dom元素,只是你不希望被截断的dom元素都需要单独的拿出来计算高度,而不能获取整个大页面的高度// 这里的children取决于你传过来的父元素,根据实际需求来获取你需要的子元素const children = ele[0].children[1].children[0].children;// 定义一个空数组,来接收需要生成图片计算完高度的dom对象let canvas:any = [];//  这里的 i 和 j 根据实际需求添加  i 是只你定义的children的每一个dom元素的索引,每计算完一个高度,进行++运算然后递归let i = 0; // 这里的 j 是如果你需要对你定义的children的子元素更深层的遍历的话,需要拿到他下面的子元素高度的话,就另定义一个j变量,进行++运算再递归let j = 0;    // scale是清晰度参数 数值越大,对应的清晰度越清晰,但是相对导出的文件大小也就越大,慎重修改,这里是根据你的窗口大小做判断const scale = window.devicePixelRatio > 1 ? window.devicePixelRatio : 2// 将dom转化为canvasfunction toCanvas() {// 这里因为我需要深层遍历children的子元素的第三个元素的子元素也就是children的孙子元素,但是前两个我没有要单独计算高度的需求,所以做了这个判断if (children.length > 1 && i<=1 ) {html2Canvas(children[i], {scale:scale,dpi: 500, // 导出pdf清晰度background: '#fff', // 背景设为白色(默认为黑色)}).then(res => { // 计算每个dom的高度,方便后面计算分页res.imgWidth = 595.28 / scale / 0.7;res.imgHeight = 592.28 / res.width * res.height / scale /0.7;canvas.push(res);i++;// 这里判断我是否已经全部将需要计算高度的节点计算完了,如果计算完高度就会添加到我定义的canvas数组里面,计算完了就执行分页并生成pdf,否则递归继续计算if (canvas.length === children.length  + children[2].children.length) {paging();toPdf();} else {toCanvas();}});}// 前面说过了,这里我需要单独计算第三个子元素的每个子元素的高度,所以如果 i>1了也就意味着遍历到第三个节点了,第三个节点我要再去获取里面的子元素,在这里面在进行转化canvaselse{html2Canvas(children[i].children[j], {scale:scale,dpi: 500, // 导出pdf清晰度background: '#fff', // 背景设为白色(默认为黑色)}).then(res => { // 计算每个dom的高度,方便后面计算分页res.imgWidth = 595.28 / scale / 0.7;res.imgHeight = 592.28 / res.width * res.height / scale/0.7 ;canvas.push(res);j++;if (canvas.length === children.length + children[2].children.length-1) {paging();toPdf();} else {toCanvas();}});}}/*** [根据dom的高度初步进行分页,会将canvas组装为一个二维数组]*/// dom 全部转化完成 开始计算分页function paging() {const imgArr = [[]];let pageH = 0;// 页面的高度let allH = 0;// 当前组所有dom的高度和let j = 0;for (let k = 0; k < canvas.length; k++) { // 涉及到k--的操作,使用for循环方便pageH += canvas[k].imgHeight;if (pageH > 841.89 && canvas[k].imgHeight < 841.89) { // 当某个页面装不下下一个dom时,则分页imgArr[j][0].allH = allH - canvas[k].imgHeight;allH = pageH = 0;k--;j++;imgArr.push([]);} else {if (canvas[k].imgHeight > 841.89) { // 特殊情况:某个dom高度大于了页面高度,特殊处理canvas[k].topH = 841.89 - (pageH - canvas[k].imgHeight);// 该dom顶部距离页面上方的距离pageH = (2 * canvas[k].imgHeight - pageH) % 841.89;canvas[k].pageH = pageH;// 该dom底部距离页面上方的距离}imgArr[j].push(canvas[k]);allH += canvas[k].imgHeight;}if (k === canvas.length - 1) imgArr[j][0].allH = allH;}canvas = imgArr;}/*** [生成PDF文件]*/function toPdf() {const PDF = new JsPDF('p', 'pt', 'a4');canvas.forEach((page, index) => {let allH = page[0].allH;let position = 20;// pdf页面偏移if (index !== 0 && allH <= 841.89) PDF.addPage();page.forEach(img => {if (img.imgHeight < 841.89) { // 当某个dom高度小于页面宽度,直接添加图片// 这里的width除以多少取决于你导出的页面在pdf页里面横向偏移的多少,你可以修改这个除数进行对页面的横向调整PDF.addImage(img.toDataURL('image/jpeg', 1.0), 'JPEG', img.imgWidth/5, position, img.imgWidth, img.imgHeight);position += img.imgHeight;allH -= img.imgHeight;} else { // 当某个dom高度大于页面宽度,则需另行处理while (allH > 0) {PDF.addImage(img.toDataURL('image/jpeg', 1.0), 'JPEG', img.imgWidth/5, position, img.imgWidth, img.imgHeight);allH -= img.topH || 841.89;position -= img.topH || 841.89;img.topH = 0;if (allH > 0) PDF.addPage();}position = img.pageH;}});});PDF.save(title + '.pdf');}toCanvas();
}
export default exportPDF;

在页面调用

import exportPDF from '@/pages/common/utils/exportPDF'
...const toPdf = () =>{exportPDF({className:"toPdf",title:caseAuthor})}
return (
//  这里如果按钮不需要被导出的话 一定要拿到你传的类名的盒子外面<div className='toPdf'><Button onClick={toPdf}>导出pdf</Button><Layout style={{ backgroundColor: '#fff' }}><Content className={css.casecontent}>......</Content></Layout></div>
)

代码到这就结束了,用的html2canvas是1.4.1版本的,所以不涉及svg不能解析的问题,如果你的svg不能解析,或者格式混乱的话,检查一下对应的样式是否生效,如果没有生效,你可以把对应的样式放在行内来写。

但是还有一定的问题没有解决,如果页面过于复杂,导出的话会有浏览器性能问题,因为要递归去获取dom节点,嵌套比较深的话,可能导出会很慢,如果有解决方案,还请大佬指点

还要实现一个需求,就是在不渲染这个页面,通过其他页面路由的id去获取到这个页面,但是不跳转,前端是完全没有知觉的去通过这个页面对应的id去生成pdf,目前我还没有想到解决办法,如果大家有好的方案和建议还请多多指点

jsPdf+html2Canvas+react实现前端页面导出pdf,并解决jspdf分页图片过长截断问题相关推荐

  1. 前端页面生成pdf方案

    前端页面生成pdf方案 使用jsPDF的html方法生成 直接将html节点传入jsPDF生成pdf,效果一般 const pdf = new jsPDF('p', 'pt', 'a4'); cons ...

  2. java jsp导出pdf文件_JSP页面导出PDF格式文件

    JSP页面导出PDF格式文件基本在前端页面可以全部完成 添加下载链接的点击事件 var downPdf = document.getElementById("downLoad"); ...

  3. iText实现HTML页面导出PDF

    iText实现HTML页面导出PDF 引言 实现效果 前期准备 实现功能 1.需要的jar包 2.封装导出类 3.需要的jar包 4.前端调用 5.模板文件 引言 最近项目中,涉及到票据导出功能,ex ...

  4. vue页面导出pdf

    vue页面导出pdf 下载依赖 yarn add html2canvas // 将页面html转换成图片 yarn add jspdf // 将图片生成pdf 定义全局函数,创建htmlToPdf.j ...

  5. 支持导出PDF文件并转换成图片格式的PDF查看控件Spire.PDFViewer

    Spire.PDFViewer for .NET是一款功能强大的PDF查看控件.它是由e-iceblue公司在2012年新推出的一款产品.它允许开发者从本地文件夹(File),stream和byte ...

  6. MATLAB图片导出PDF格式,并且控制图片白色边框大小——非代码方法

    Mtalab生成的图片,可以另存为pdf格式,但是实际情况却是下图所示,pdf纸张大小为A4,实际图却很小,显然不行. 这是由于纸张大小(PaperSize)和图片大小(PaperPosition)不 ...

  7. uniapp页面导出pdf

    文章目录 前言 一.使用步骤 1.安装依赖 2.main引入 总结 前言 uniapp导出页面级的pdf.具体功能没有测试完成.已经交给后端实现,前端这边分页处文字没有截断,图片和echart导出暂时 ...

  8. vue前端页面转PDF

    需求说明 公司最近想出一份报告,报告内容包含地图展示,折线图还有各种文字说明,跟后台沟通反映后台无法实现,所以就前端想办法来实现此功能. 所用插件 html2canvas jspdf html &am ...

  9. 前端vue导出pdf

    1.下载插件 npm install html2canvas npm install jspdf 2.创建htmlToPdf.js** 2-1(一页展示所有内容,可避免分页截断) import htm ...

最新文章

  1. 图像处理中的Mask是什么
  2. Gartner:人工智能将改变个人设备领域的游戏规则
  3. 设计sample语言的词法分析器_重现木兰编程语言(十)——比较、循环,一个语法设计特色
  4. mysql当前时间减一分钟_MySQL数据库事务的机制【总结】
  5. 深度2万字好文:图像处理-基于 PyTorch 的 YOLO v5 表情识别(附源代码)
  6. [转]在Fedora上安装Oracle 11g XE
  7. java模拟火车站买票的过程_Java常用代理
  8. Redis 集群_主从复制_哨兵模型
  9. java zar_唬人的Java泛型并不难
  10. 【12c】12c RMAN新特性之通过网络远程恢复数据库(RESTORE/Recover from Service)
  11. HDU 1800 贪心
  12. 《Joel On Software》读后
  13. MyBatis自动生成步骤
  14. 解决win10下桌面右击新建没有文本文档(.txt)的问题
  15. 【RPA】PDF生成器FPDF(Python篇)
  16. 移动APP测试用例设计的关注点
  17. 用连接数据库的方式读取excel
  18. [4G5G专题-9]:RRU 数字上变频DUC与数字下变频DDC
  19. 【转载】转别人写的HTMLCSS 详细笔记脉络--很详细
  20. Windows 10操作系统常用快捷键介绍

热门文章

  1. MFC创建MEDIA_PLAYER播放器,简单教程
  2. {我喜欢你,就像喜欢当时的自己。}---《那些年,我们一起追的女孩》影评。(By:Janice)
  3. nacos的服务发现详解
  4. Java:JDK版本特性汇总
  5. Shell(3)管道与重定向
  6. js代码怎么实现合并图片
  7. PC上一些比较好用的软件
  8. 关于查询功能中的重置
  9. Freenas硬件需求
  10. 以科技之力 践行企业社会责任