import html2canvas from 'html2canvas'
import JsPDF from 'jspdf'let exportTime = '';const exportPdf = {/*** 1.图片清晰问题* 2.导出图片改造* pdf* @param {配置内容} options* options:{*  elementId:'#xxx',*  fileName:'文件名',*  type: 'pdf', 导出类型 pdf || img (默认pdf)*  load:false //是否下载*  titleData: {*    title1: '标题1',*    title2: '标题2',*    title3: '标题3',*  },*  exportTime: '导出时间',* }*/export(options, eventFn) {if (!options.elementId) return;exportTime = options.exportTime || null;// 如果这个页面有左右移动,canvas 也要做响应的移动,不然会出现canvas 内容不全const xOffset = window.pageXOffset// 避免笔下误 灯下黑 统一写const A4_WIDTH = 592.28;const A4_HEIGHT = 841.89;const element = document.querySelector(options.elementId);// 根据A4的宽高计算DOM页面一页应该对应的高度let pageHeight = element.offsetWidth / A4_WIDTH * A4_HEIGHT;// 将所有不允许被截断的元素进行处理let wholeNodes = document.querySelectorAll('.export-chart-cont');for (let i = 0; i < wholeNodes.length; i++) {//1、 判断当前的不可分页元素是否在两页显示const topPageNum = Math.ceil((wholeNodes[i].offsetTop) / pageHeight);const bottomPageNum = Math.ceil((wholeNodes[i].offsetTop + wholeNodes[i].offsetHeight) / pageHeight);if (topPageNum !== bottomPageNum) {//说明该dom会被截断// 2、插入空白块使被截断元素下移let divParent = wholeNodes[i].parentNodelet newBlock = document.createElement('div')newBlock.className = 'emptyDiv'newBlock.style.background = '#fff'// 3、计算插入空白块的高度 可以适当流出空间使得内容太靠边,根据自己需求而定let _H = topPageNum * pageHeight - wholeNodes[i].offsetTopnewBlock.style.height = _H + 100 + 'px'divParent.insertBefore(newBlock, wholeNodes[i])}}let w = element.offsetWidth // 获取dom 宽度let h = element.offsetHeight // 获取dom 高度$(options.elementId).scrollTop(0);  // 只是截取可见范围以及以下的区域,所以先将滚动条置顶document.body.scrollTop = 0; // IE的document.documentElement.scrollTop = 0; // 其他let opts = {// x: options.x ? options.x : 400,// y: 100,width: w,height: h,allowTaint: true,scrollY: 0,scrollX: 0,scale: 2,// logging: true,};if (options.w) opts.width = options.w;html2canvas(element, opts).then(canvas => {//dom 已经转换为canvas 对象,可以将插入的空白块删除了let emptyDivs = document.querySelectorAll('.emptyDiv')for (let i = 0; i < emptyDivs.length; i++) {emptyDivs[i].parentNode.removeChild(emptyDivs[i])}// 有一点重复的代码let contentWidth = canvas.width;let contentHeight = canvas.height;// 一页pdf显示html页面生成的canvas高度;let pageHeight = contentWidth / A4_WIDTH * A4_HEIGHT;// 未生成pdf的html页面高度let leftHeight = contentHeight;// 页面偏移let position = 0;var pdf = new JsPDF('', 'pt', 'a4');// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高var imgWidth = 585.28; // 减去左,右辆边边距var imgHeight = imgWidth / contentWidth * contentHeight;var imgPaddingL = 5; // 左边距// 标题let titleImg = new Image();titleImg.src = this.getTitleImg(imgWidth, 75, options.titleData);titleImg.onload = () => {const titleImgWatermark = this.addWatermarkByTitle(titleImg, imgWidth, 75)pdf.addImage(titleImgWatermark, 'JPEG', imgPaddingL, 20, imgWidth, 75, 'titleImg');}pageHeight -= 75;position += 75;var img = new Image();img.src = canvas.toDataURL('image/jpeg', 1.0);img.onload = () => {const pdfImg = this.addWatermark(img, img.width, img.height);//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)//当内容未超过pdf一页显示的范围,无需分页if (leftHeight < pageHeight) {pdf.addImage(pdfImg, 'JPEG', imgPaddingL, 80, imgWidth, imgHeight);} else {while (leftHeight > 0) {console.log('第n页');pdf.addImage(pdfImg, 'JPEG', imgPaddingL, position, imgWidth, imgHeight)leftHeight -= pageHeight;position -= 841.89;//避免添加空白页if (leftHeight > 0) {pdf.addPage();}}}if (options.type != 'img') { //导出pdfoptions.load ? pdf.save(`${options.fileName}.pdf`) : false;} else { //导出imgvar downloadElement = document.createElement("a");downloadElement.href = img.src;downloadElement.download = FileName; //下载后文件名document.body.appendChild(downloadElement);downloadElement.click(); //点击下载document.body.removeChild(downloadElement); //下载完成移除元素}if (typeof eventFn == 'function') eventFn(img, pdf);}});},// 截图加水印addWatermark(imgData, imgWidth, imgHeight) {// 单个水印var tpl = '<canvas width = "'+ 420 +'px"  height = "'+ 250 +'px" style="display:none;"></canvas>';var cw = $(tpl)[0];var ctxl = cw.getContext("2d");ctxl.font = "14pt microsoft yahei";ctxl.rotate(-20 * Math.PI /180);ctxl.fillStyle = "rgba(0,0,0,0.3)";ctxl.textAlign = 'center';exportTime ? ctxl.fillText(exportTime, (420 / 2), (250 / 2)) : '';ctxl.rotate(20 * Math.PI / 180);// 单个水印平铺var tmpl = '<canvas width = "' + imgWidth + '"  height = "' + imgHeight + '"></canvas>';var canvas1 = $(tmpl)[0];var ctx = canvas1.getContext("2d");ctx.drawImage(imgData, 0, 0);var pat = ctx.createPattern(cw, "repeat");ctx.rect(0, 0, imgWidth, imgHeight);ctx.fillStyle = pat;ctx.fill();var img = canvas1.toDataURL('image/jpeg', 1.0);return img;},// 标题加水印addWatermarkByTitle(imgData, imgWidth, imgHeight) {if (!imgData) return nullimgWidth = imgWidth * 2;imgHeight = imgHeight * 2;// 单个水印var tpl = '<canvas width = "' + 290 + 'px"  height = "' + 75 * 2 + 'px" style="display:none;"></canvas>';var cw = $(tpl)[0];var ctxl = cw.getContext("2d");ctxl.font = "14px microsoft yahei";ctxl.rotate(-20 * Math.PI / 180);ctxl.fillStyle = "rgba(0,0,0,0.2)";ctxl.textAlign = 'center';exportTime ? ctxl.fillText(`${exportTime}`, (145 / 2), 75) : ctxl.fillText((145 / 2), 75);ctxl.rotate(20 * Math.PI / 180);// 单个水印平铺var tmpl = '<canvas width = "' + imgWidth + '"  height = "' + imgHeight + '"></canvas>';var canvas1 = $(tmpl)[0];var ctx = canvas1.getContext("2d");ctx.drawImage(imgData, 0, 0);var pat = ctx.createPattern(cw, "repeat");ctx.rect(0, 0, imgWidth, imgHeight);ctx.fillStyle = pat;ctx.fill();var img = canvas1.toDataURL('image/jpeg', 1.0);return img;},// 绘画标题getTitleImg(imgWidth, imgHeight, info) {if (!info) return nullimgWidth = imgWidth * 2;imgHeight = imgHeight * 2;const scale = window.devicePixelRatio;const titleCanvasBox = '<canvas width = "' + imgWidth + 'px"  height = "' + imgHeight + 'px"></canvas>';const titleCanvas = $(titleCanvasBox)[0];let tcCtx = titleCanvas.getContext("2d");tcCtx.fillStyle = "#fff";tcCtx.fillRect(0, 0, imgWidth, imgHeight);tcCtx.font = "18px microsoft yahei";tcCtx.fillStyle = "#000";tcCtx.textAlign = 'center';tcCtx.fillText(info.title1, (imgWidth / 2), 30);tcCtx.font = "12px microsoft yahei";tcCtx.fillStyle = "#000";tcCtx.textAlign = 'center';tcCtx.fillText(info.title2, (imgWidth / 2), 55);tcCtx.font = "12px microsoft yahei";tcCtx.fillStyle = "#000";tcCtx.textAlign = 'center';tcCtx.fillText(info.title3, (imgWidth / 2), 75);const titleImg = titleCanvas.toDataURL('image/jpeg', 1.0);return titleImg;},};export default exportPdf;

前端将图表和表格导出为PDF相关推荐

  1. 使用 jsPDF- Autotable 将 HTML 表格导出为 PDF

    介绍   您一定从 Internet 下载过 PDF 文件.它可能是考试表格.费用收据.发票或任何此类文件.您有没有想过这些内容是如何一键以 PDF 的形式下载的?今天,我们将在本文中执行相同的操作. ...

  2. 【前端html页面数据导出为pdf文件】

    [前端html页面数据导出为pdf文件] 文前白话 在网页端导出 Excel 数据表格保存本地 前端html页面数据导出为pdf文件 文前白话 项目需要,将网页端查询的数据结果与数据分析结果导出文件, ...

  3. 前端表格导出为excel方法合集

    前端表格导出为excel方法合集 近来遇到了前端表格保存为excel的需求,通过查阅多方资料,总结了3种方法,下面一一进行展示,有不正确的地方,望指正.主要包括两种导出方法--纯前端导出和前端接收后端 ...

  4. 前端复杂表格导出excel,一键导出 Antd Table 看这篇就够了(附源码)

    前端导出 excel 的需求很多,但市面上好用的库并不多,讲明白复杂使用场景的文章更少. 本文将以文字 + demo 源码的形式,力求讲清楚满足 99% 使用场景的终极 excel 导出方案. 如果项 ...

  5. Python自动化办公:将Excel表格内容批量导出为PDF文件

    Python自动处理Excel表格数据 序言 代码实现 序言 上一篇咱们实现了多个表格数据合并到一个表格,本次咱们来学习如何将表格数据分开导出为PDF文件. 部分数据 然后需要安装一下这个软件 wkh ...

  6. 通过前端实现导出生成pdf文件并下载

    通过前端实现导出生成pdf文件并下载 使用 jspdf.js + html2canvas 插件,实现前端生成pdf 并下载的功能 步骤如下 1.先通过npm 安装插件 npm install jspd ...

  7. Java代码实现PDF中表格导出到Excel

    表格常见于 PDF 发票和财务报告中.您可能会遇到需要将 PDF 表格数据导出到 Excel 中的情况,以便您可以使用 MS Excel 提供的工具对数据进行分析.本文介绍了如何使用 Spire.Of ...

  8. Vue前端表格导出Excel文件

    前言 分享一个Vue前端导出Excel文件的方法.记录学习! 功能需求:将表格的全部数据导出Excel格式的文件 前端:Vue3+Element-Plus 这个导出方法全部为前端操作,后端只需要传入表 ...

  9. js导出变量 vue_vue.js前端实现excel表格导出和获取headers里的信息

    前段时间写过一篇文章基于element实现后台管理系统,并提到excel表格导出功能,可能描述不是很详细,现在单独整理列出. 后端提供的接口: // 下载分拣列表 export function ge ...

最新文章

  1. 智源社区票选2021 AI十大进展出炉!
  2. Android 判断当前屏幕是横屏还是竖屏
  3. 创业公司做数据分析(三)用户行为数据采集系统 (转)
  4. webpack 工作方式
  5. python匿名函数lambda_python的匿名函数lambda解释及用法
  6. java 观察者模式示例_Java中的观察者设计模式-示例教程
  7. JavaScript事件处理的三种方式(转)
  8. 专栏导读:数据驱动的优化
  9. mysql设置utf8_unicode_ci字符集php页面输出??乱码的解决方法
  10. 硬盘测试软件di,磁盘检测(Folder Size Professional)
  11. php ZeroMQ 的使用
  12. Android 运行时权限检测流程,申请危险权限组权限代码
  13. S3C2440 SDRAM内存驱动
  14. 快速部署安装libart_lgp
  15. 贪心算法(Greedy Algorithm)理论篇
  16. idea显示Multiple Spring Boot run configurations were detected. Services allows to manage multiple run
  17. C#将日期转化成英文
  18. java如何连接与断开SQL server2008数据库
  19. 【精美后台管理系统模版->UI界面欣赏】
  20. It was possible to detect the usage of the deprecated TLSv1.0 and/or TLSv1.1 protocol on this system

热门文章

  1. 软件产品登记证书和软著区别 软件产品登记证书怎么申请
  2. Chrome广告屏蔽
  3. arcgis10.2破解版教程(中文版)
  4. ISP是什么?我们常用的ISP
  5. 25页国有企业数字化转型ppt,解决4个典型痛点场景,实现提质增效
  6. 基于嵌入式Win CE系统的电能质量监测仪
  7. STC单片机操作系统——RTX51 Tiny
  8. 2021年低压电工报名考试及低压电工实操考试视频
  9. 杰理AC692X---添加串口打印调试
  10. 系统架构师(十三)开发管理