You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从服务端导出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:40:58