当前位置: 首页 > news >正文

vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)

vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)

  • 1、安装依赖
  • 2、在utils中创建htmlToPDF.js文件
  • 3、在vue中引入并使用

1、安装依赖

npm install --save html2canvas  // 页面转图片
npm install jspdf --save  // 图片转pdf

2、在utils中创建htmlToPDF.js文件

// 页面导出为pdf格式 //title表示为下载的标题,html表示document.querySelector('#myPrintHtml')
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
var noTableHeight = 0 //table外的元素高度export const htmlPdf = (title, html, fileList, type) => {// type传有效值pdf则为横版if (fileList) {const pageHeight = Math.floor(277 * html.scrollWidth / 190) + 20 //计算pdf高度for (let i = 0; i < fileList.length; i++) { //循环获取的元素const multiple = Math.ceil((fileList[i].offsetTop + fileList[i].offsetHeight) / pageHeight) //元素的高度if (isSplit(fileList, i, multiple * pageHeight)) { //计算是否超出一页var _H = '' //向pdf插入空白块的内容高度if (fileList[i].localName !== 'tr') { //判断是不是表格里的内容_H = multiple * pageHeight - (fileList[i].offsetTop + fileList[i].offsetHeight)} else {_H = multiple * pageHeight - (fileList[i].offsetTop + fileList[i].offsetHeight + noTableHeight) + 20}var newNode = getFooterElement(_H)  //向pdf插入空白块的内容const divParent = fileList[i].parentNode // 获取该div的父节点const next = fileList[i].nextSibling // 获取div的下一个兄弟节点// 判断兄弟节点是否存在if (next) {// 存在则将新节点插入到div的下一个兄弟节点之前,即div之后divParent.insertBefore(newNode, next)} else {// 否则向节点添加最后一个子节点divParent.appendChild(newNode)}}}}html2Canvas(html, {allowTaint: false,taintTest: false,logging: false,useCORS: true,dpi: window.devicePixelRatio * 1,scale: 1 // 按比例增加分辨率}).then(canvas => {var pdf = new JsPDF('p', 'mm', 'a4') // A4纸,纵向var ctx = canvas.getContext('2d')var a4w = type ? 277 : 190; var a4h = type ? 190 : 277 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度var renderedHeight = 0while (renderedHeight < canvas.height) {var page = document.createElement('canvas')page.width = canvas.widthpage.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 += imgHeightif (renderedHeight < canvas.height) {pdf.addPage()// 如果后面还有内容,添加一个空页}// delete page;}// 保存文件pdf.save(title + '.pdf')})
}
// pdf截断需要一个空白位置来补充
const getFooterElement = (remainingHeight, fillingHeight = 0) => {const newNode = document.createElement('div')newNode.style.background = '#ffffff'newNode.style.width = 'calc(100% + 8px)'newNode.style.marginLeft = '-4px'newNode.style.marginBottom = '0px'newNode.classList.add('divRemove')newNode.style.height = (remainingHeight + fillingHeight) + 'px'return newNode
}
const isSplit = (nodes, index, pageHeight) => {// 判断是不是tr 如果不是高度存起来// 表格里的内容要特殊处理// tr.offsetTop 是tr到table表格的高度// 所以计算高速时候要把表格外的高度加起来// 生成的pdf没有表格了这里可以不做处理 直接计算就行if (nodes[index].localName !== 'tr') {  //判断元素是不是trnoTableHeight += nodes[index].clientHeight}if (nodes[index].localName !== 'tr') {return nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight} else {return nodes[index].offsetTop + nodes[index].offsetHeight + noTableHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight + noTableHeight > pageHeight}
}

3、在vue中引入并使用

<template><div><button class="primary-btn" @click="handleExport">导出</button><div class="check-wrapper" id="pdfRef"><div class="page1-box pdfRef">11</div><div class="page2-box pdfRef">11</div><div class="page3-box pdfRef">11</div><div class="page4-box pdfRef">11</div><div class="page5-box pdfRef">11</div><div class="page6-box pdfRef">11</div><div class="page7-box pdfRef">11</div><div class="page8-box pdfRef">11</div></div></div>
</template>
<script setup>// 引入方法import { htmlPdf } from "@/utils/htmlToPDF.js"  // 导出成PDFconst handleExport = (name) => {var fileName= '投资评审报告'const fileList = document.getElementsByClassName('pdfRef')   // 很重要htmlPdf(fileName, document.querySelector('#pdfRef'), fileList)}
</script>
http://www.lryc.cn/news/168002.html

相关文章:

  • 软件测试:黑盒测试用例的四种设计方法
  • 数据库开发-MySQL基础DQL和多表设计
  • PowerDesigner 逆向工程以及IDEA中UML插件
  • 企业架构LNMP学习笔记56
  • [Linux入门]---搭建Linux环境
  • 性能测试知多少---性能分析与调优的原理
  • “对象创建”模式
  • ipad手写笔有必要买吗?好用的平板触控笔
  • OpenGL ES视频特效开发参考Shadertoy参数详解参考Godot文档
  • java:逆序排序的三种方法
  • pgsql操作json类型
  • Thinkphp6 配置并使用redis图文详解 小皮面板
  • 模拟实现链式二叉树及其结构学习——【数据结构】
  • 基于go版本的LoraWAN Server 的470MHz频段的设置
  • C与C++的函数相互调用
  • MySQL架构介绍与说明
  • three3D的vite+vue版本基础代码
  • 实现按钮悬停动画
  • 【C++】深拷贝和浅拷贝 ② ( 默认拷贝构造函数是浅拷贝 | 代码示例 - 浅拷贝造成的问题 )
  • 【Selenium】webdriver.ChromeOptions()官方文档参数
  • pytorch代码实现之动态卷积模块ODConv
  • 动态规划:子序列问题(C++)
  • ORACLE的分区(一)
  • 【数据结构】C++实现二叉搜索树
  • Python中Mock和Patch的区别
  • sql server 查询某个字段是否有值 返回bool类型
  • 紫光展锐5G芯T820 解锁全新应用场景,让机器人更智能
  • 秋招前端面试题总结
  • 【入门篇】ClickHouse 数据类型
  • 关于Python数据分析,这里有一条高效的学习路径