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

react页面指定dom转pdf导出

      • 1. 使用jsPDF+html2canvas将页面转成图片然后导出
      • 2. 自定义创建iframe调用iframe.print()进行页面打印转pdf导出
      • 3. 使用react-to-print插件打印pdf

1. 使用jsPDF+html2canvas将页面转成图片然后导出

缺点:页面过长可能会导出失败,并且由于电脑分辨率的问题导致导出文件模糊不清

实现代码:

import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';export function downToPdf(className: string, name: string) {let elements = document.getElementsByClassName(className); // 获取指定类名的元素if (elements.length === 0) {return;}let element: any = elements[0]; // 使用第一个匹配到的元素let w = element.offsetWidth; // 获取容器的宽度let h = element.offsetHeight; // 获取容器的高度let canvas = document.createElement("canvas");canvas.width = w;canvas.height = h;// 默认横向没有滚动条的情况,因为offsetLeft有无滚动条的时候存在差值,因此// translate的时候,要把这个差值去掉html2canvas(element, {  // 设置option可去除灰色色块allowTaint: false,useCORS: true,scale: 1.2, // 用于渲染的比例。默认为浏览器设备像素比率backgroundColor: '#F5F5F5',windowWidth: element.scrollWidth,windowHeight: element.scrollHeight}).then(function (canvas) {let contentWidth = canvas.width;let contentHeight = canvas.height;// 一页pdf显示html页面生成的canvas高度let pageHeight = (contentWidth / 592.28) * 841.89;// 未生成pdf的html页面高度let leftHeight = contentHeight;// 页面偏移let position = 0;// a4纸的尺寸[595.28,841.89]pt,html页面生成的canvas在pdf中图片的宽高let imgWidth = 595.28;let imgHeight = (592.28 / contentWidth) * contentHeight - 56.7;  // 上下边距10mmlet pageData = canvas.toDataURL("image/jpeg", 1.0);let pdf = new jsPDF("p", "pt", "a4");// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)// 当内容未超过pdf一页显示的范围,无需分页if (leftHeight < pageHeight) {pdf.addImage(pageData, "JPEG", 0, 28.35, imgWidth, imgHeight);} else {// 分页while (leftHeight > 0) {pdf.addImage(pageData, "JPEG", 0, position + 28.35, imgWidth, imgHeight);leftHeight -= pageHeight; // 加上页面高度和上下的页面距position -= 841.89;// 避免添加空白页if (leftHeight > 0) {pdf.addPage();}}}pdf.save(name + ".pdf");});
}

2. 自定义创建iframe调用iframe.print()进行页面打印转pdf导出

缺点:对于echarts图表可能出现样式问题

代码实现:

export const printPDF = (dom: any) => {// 将canvas元素转换为图片convertCanvasToImages(dom);
};// 写入iframe
function writeIframe(dom: any) {const iframe: any = document.createElement("iframe");iframe.style.position = "absolute";iframe.style.width = "0";iframe.style.height = "0";iframe.style.top = "-10px";iframe.style.left = "-10px";document.body.appendChild(iframe);const doc: any = iframe.contentDocument;doc.open();doc.write(getStyle() + getHtml(dom));doc.close();iframe.onload = function () {iframe.contentWindow.print();setTimeout(() => {document.body.removeChild(iframe);}, 100);};
}// 获取样式
function getStyle() {const styles = document.querySelectorAll("style,link");let str = "";for (let i = 0; i < styles.length; i++) {str += styles[i].outerHTML;}str += `<style>@media print {html,body{height: auto;margin: 0;}body{zoom: 100%;}img{max-width: 100% !important;height: auto !important;page-break-inside: auto;break-inside: auto;}@page {margin: 0;}}</style>`;return str;
}// 获取dom
function getHtml(dom: any) {return dom.outerHTML;
}// 将canvas元素转换为图片
function convertCanvasToImages(dom: any) {const canvasElements = dom.querySelectorAll('canvas');let convertedCount = 0;if (canvasElements.length === 0) {writeIframe(dom);return;}canvasElements.forEach((canvas: any) => {const img = document.createElement('img');img.src = canvas.toDataURL('image/png');img.style.width = '100%';img.style.height = 'auto';canvas.parentNode.replaceChild(img, canvas);convertedCount++;if (convertedCount === canvasElements.length) {writeIframe(dom);}});
}

3. 使用react-to-print插件打印pdf

缺点:对于大量echarts图表可能会随机几个出现样式问题

代码实现:

  1. 下载: yarn add react-to-print
  2. 引入插件

import {useReactToPrint} from “react-to-print”;

  1. 使用
import React, { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';const PrintComponent = React.forwardRef((props, ref) => {return (<div ref={ref} style={{ width: '100%', height: 'auto' }}>{/* 你的长内容 */}<div>Page 1</div><div>Page 2</div><div>Page 3</div>{/* 更多内容 */}</div>);
});const App = () => {const printRef = useRef();// 打印功能const handlePrint = useReactToPrint({content: () => printRef.current,pageStyle: `@page {size: A4;margin: 0;}@media print {body, html {height: auto;overflow: initial !important;  // 重要,如果不分页需要加上margin: 0;}body{zoom: 100%;}img{max-width: 100% !important;height: auto !important;page-break-inside: auto;break-inside: auto;}}`,removeAfterPrint: true,documentTitle: `报告名称`,});return (<div><PrintComponent ref={printRef} /><button onClick={handlePrint}>打印</button></div>);
};export default App;

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 网络通信介绍
  • css3 中的伪类和伪元素
  • 数学建模-Topsis(优劣解距离法)
  • Node.js实现文件下载
  • 记录些MySQL题集(15)
  • idea Apipost 插件导出接口文档字段类型全部是string
  • webpack和vite
  • (算法)区间调度问题
  • electron 的nsis配置
  • myeclipse开发ssm框架项目图书管理系统 mysql数据库web计算机毕业设计项目
  • 高数知识补充----矩阵、行列式、数学符号
  • 『 Linux 』简单日志插件
  • IDEA自带的Maven 3.9.x无法刷新http nexus私服
  • Ubuntu 24.04安装Jellyfin媒体服务器图解教程
  • 【大型实战】企业网络实验(华为核心交换、ESXI7.0vmware虚拟机、DHCP中继、服务端网络及用户端网络配置)
  • 0x05 Python数据分析,Anaconda八斩刀
  • ComponentOne 2017 V2版本正式发布
  • docker python 配置
  • Effective Java 笔记(一)
  • Java到底能干嘛?
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • PHP的Ev教程三(Periodic watcher)
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 从0实现一个tiny react(三)生命周期
  • 记一次和乔布斯合作最难忘的经历
  • 检测对象或数组
  • 你真的知道 == 和 equals 的区别吗?
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 小试R空间处理新库sf
  • 与 ConTeXt MkIV 官方文档的接驳
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #pragma data_seg 共享数据区(转)
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (Charles)如何抓取手机http的报文
  • (十一)c52学习之旅-动态数码管
  • (四)React组件、useState、组件样式
  • (详细文档!)javaswing图书管理系统+mysql数据库
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)3D模板阴影原理
  • (转)甲方乙方——赵民谈找工作
  • . Flume面试题
  • .describe() python_Python-Win32com-Excel
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .net 获取url的方法
  • .NET企业级应用架构设计系列之结尾篇
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .net中应用SQL缓存(实例使用)
  • @component注解的分类
  • @font-face 用字体画图标