如何从服务端导出React MUI X Charts为PDF文件
解决MUI图表导出PDF的方案
一、修复现有base64转换+后端pdfmake的问题
你之前转base64传后端失败,大概率是DOM获取时机不对或目标元素错误,按以下步骤调整:
1. 正确获取图表容器DOM
给MUI图表套一个外层div,用useRef获取这个容器,而非直接操作PieChart组件本身:
import { useRef } from 'react'; import { PieChart, pieArcLabelClasses } from '@mui/x-charts'; const TicketPieChart = ({ ticketpie, t }) => { const chartContainerRef = useRef(null); // 转换为base64并传给后端 const handleExport = async () => { if (!chartContainerRef.current) return; // 用html2canvas截取容器内容 const canvas = await html2canvas(chartContainerRef.current); const base64Image = canvas.toDataURL('image/png'); // 发送到后端接口 await fetch('/api/generate-pdf', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chartImage: base64Image }) }); }; return ( <div ref={chartContainerRef}> <PieChart series={[ { data: [ { value: ticketpie.treated, label: t('dashboard.tickets.treated') }, { value: ticketpie.nontreated, label: t('dashboard.tickets.nonTreated') } ], innerRadius: 60, highlightScope: { faded: 'global', highlighted: 'item' }, faded: { additionalRadius: -30, color: 'gray' }, }, ]} sx={{ [`& .${pieArcLabelClasses.root}`]: { fill: 'white', fontWeight: 'bold', }, }} height={250} /> <button onClick={handleExport}>导出PDF</button> </div> ); };
2. 后端pdfmake正确处理图片
确保后端接收base64后,在pdfmake的文档定义中正确引用:
const pdfMake = require('pdfmake'); // 示例Node.js接口 app.post('/api/generate-pdf', (req, res) => { const { chartImage } = req.body; const docDefinition = { content: [ { text: '工单处理统计', fontSize: 16, bold: true, margin: [0, 0, 0, 15] }, // 直接使用base64字符串作为图片源 { image: chartImage, width: 280, alignment: 'center' } ] }; const printer = new pdfMake(); const pdfDoc = printer.createPdfKitDocument(docDefinition); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'attachment; filename="ticket-stat.pdf"'); pdfDoc.pipe(res); pdfDoc.end(); });
关键注意点
- 等待图表完全渲染后再执行转换:如果是页面加载后自动导出,可在
useEffect中加延迟,或监听MUI图表的onRenderComplete回调。 - 确保html2canvas版本足够新:旧版本对SVG渲染的MUI图表支持可能存在问题,建议安装最新版。
二、前端直接导出PDF(无需后端)
如果不想依赖后端,可直接用html2canvas + jsPDF在前端生成PDF,步骤更简单:
import { useRef } from 'react'; import { PieChart, pieArcLabelClasses } from '@mui/x-charts'; import html2canvas from 'html2canvas'; import jsPDF from 'jspdf'; const TicketPieChart = ({ ticketpie, t }) => { const chartContainerRef = useRef(null); const exportToPDF = async () => { if (!chartContainerRef.current) return; const canvas = await html2canvas(chartContainerRef.current); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const imgWidth = 210; // A4纸宽度 const imgHeight = (canvas.height * imgWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 20, imgWidth, imgHeight); pdf.save('ticket-stat.pdf'); }; return ( <div ref={chartContainerRef}> <PieChart {/* 你的图表配置不变 */} /> <button onClick={exportToPDF}>前端导出PDF</button> </div> ); };
三、更换图表库(如果MUI图表导出始终有问题)
如果上述方法都无法解决,可以更换为导出支持更完善的图表库:
1. Recharts
生态成熟,支持直接获取SVG内容,转换为图片或PDF更稳定:
import { PieChart, Pie, Cell, ResponsiveContainer } from 'recharts'; import { useRef } from 'react'; const RechartPie = ({ ticketpie, t }) => { const chartRef = useRef(null); const exportChart = () => { if (!chartRef.current) return; const svgContent = chartRef.current.innerHTML; // 将SVG转为base64图片 const base64 = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgContent))); // 后续用jsPDF或传给后端处理 }; return ( <ResponsiveContainer width="100%" height={250} ref={chartRef}> <PieChart> <Pie data={[ { value: ticketpie.treated, name: t('dashboard.tickets.treated') }, { value: ticketpie.nontreated, name: t('dashboard.tickets.nonTreated') } ]} innerRadius={60} outerRadius={80} label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`} /> </PieChart> </ResponsiveContainer> ); };
2. Chart.js
有官方导出插件chartjs-plugin-export,可一键导出图片或PDF,配置简单。
内容的提问来源于stack exchange,提问作者HamzaDev
相关产品推荐
相关产品推荐

