前端将图表和表格导出为PDF
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相关推荐
- 使用 jsPDF- Autotable 将 HTML 表格导出为 PDF
介绍 您一定从 Internet 下载过 PDF 文件.它可能是考试表格.费用收据.发票或任何此类文件.您有没有想过这些内容是如何一键以 PDF 的形式下载的?今天,我们将在本文中执行相同的操作. ...
- 【前端html页面数据导出为pdf文件】
[前端html页面数据导出为pdf文件] 文前白话 在网页端导出 Excel 数据表格保存本地 前端html页面数据导出为pdf文件 文前白话 项目需要,将网页端查询的数据结果与数据分析结果导出文件, ...
- 前端表格导出为excel方法合集
前端表格导出为excel方法合集 近来遇到了前端表格保存为excel的需求,通过查阅多方资料,总结了3种方法,下面一一进行展示,有不正确的地方,望指正.主要包括两种导出方法--纯前端导出和前端接收后端 ...
- 前端复杂表格导出excel,一键导出 Antd Table 看这篇就够了(附源码)
前端导出 excel 的需求很多,但市面上好用的库并不多,讲明白复杂使用场景的文章更少. 本文将以文字 + demo 源码的形式,力求讲清楚满足 99% 使用场景的终极 excel 导出方案. 如果项 ...
- Python自动化办公:将Excel表格内容批量导出为PDF文件
Python自动处理Excel表格数据 序言 代码实现 序言 上一篇咱们实现了多个表格数据合并到一个表格,本次咱们来学习如何将表格数据分开导出为PDF文件. 部分数据 然后需要安装一下这个软件 wkh ...
- 通过前端实现导出生成pdf文件并下载
通过前端实现导出生成pdf文件并下载 使用 jspdf.js + html2canvas 插件,实现前端生成pdf 并下载的功能 步骤如下 1.先通过npm 安装插件 npm install jspd ...
- Java代码实现PDF中表格导出到Excel
表格常见于 PDF 发票和财务报告中.您可能会遇到需要将 PDF 表格数据导出到 Excel 中的情况,以便您可以使用 MS Excel 提供的工具对数据进行分析.本文介绍了如何使用 Spire.Of ...
- Vue前端表格导出Excel文件
前言 分享一个Vue前端导出Excel文件的方法.记录学习! 功能需求:将表格的全部数据导出Excel格式的文件 前端:Vue3+Element-Plus 这个导出方法全部为前端操作,后端只需要传入表 ...
- js导出变量 vue_vue.js前端实现excel表格导出和获取headers里的信息
前段时间写过一篇文章基于element实现后台管理系统,并提到excel表格导出功能,可能描述不是很详细,现在单独整理列出. 后端提供的接口: // 下载分拣列表 export function ge ...
最新文章
- 智源社区票选2021 AI十大进展出炉!
- Android 判断当前屏幕是横屏还是竖屏
- 创业公司做数据分析(三)用户行为数据采集系统 (转)
- webpack 工作方式
- python匿名函数lambda_python的匿名函数lambda解释及用法
- java 观察者模式示例_Java中的观察者设计模式-示例教程
- JavaScript事件处理的三种方式(转)
- 专栏导读:数据驱动的优化
- mysql设置utf8_unicode_ci字符集php页面输出??乱码的解决方法
- 硬盘测试软件di,磁盘检测(Folder Size Professional)
- php ZeroMQ 的使用
- Android 运行时权限检测流程,申请危险权限组权限代码
- S3C2440 SDRAM内存驱动
- 快速部署安装libart_lgp
- 贪心算法(Greedy Algorithm)理论篇
- idea显示Multiple Spring Boot run configurations were detected. Services allows to manage multiple run
- C#将日期转化成英文
- java如何连接与断开SQL server2008数据库
- 【精美后台管理系统模版->UI界面欣赏】
- It was possible to detect the usage of the deprecated TLSv1.0 and/or TLSv1.1 protocol on this system