您的位置:首页 > 汽车 > 时评 > react页面指定dom转pdf导出

react页面指定dom转pdf导出

2024/9/8 8:48:18 来源:https://blog.csdn.net/qq_52476758/article/details/140497320  浏览:    关键词:react页面指定dom转pdf导出

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

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;

4. 利用@media print样式打印页面局部元素

使用该方式,不需要更改浏览器的原生打印,只需要样式控制即可打印出指定部分的内容

  1. 页面结构
    在这里插入图片描述
  2. 样式控制
@media print {@page {size: A4;margin: 0;}.ant-button, #zdns-header, .ant-notification {display: none;}.reportTemplateScene {border: none;margin: 0;height: auto;overflow: initial !important;page-break-inside: avoid; /* 避免分页中断 */}#root > div {height: auto; /* 确保内容不会被固定高度限制 */}/* 移除祖父节点的滚动条样式 */.ant-spin-container::-webkit-scrollbar,.ant-spin-container::-webkit-scrollbar-thumb,.ant-spin-container::-webkit-scrollbar-track {display: none;}/* 确保祖父节点在打印时不显示滚动条 */.ant-spin-container {overflow: hidden !important;padding: 0 !important;}/* 确保所有内容都可见 */body, html {overflow: visible !important;}/* 确保所有内容都打印出来 */* {visibility: visible !important;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com