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

使用React Hooks时如何导出ApexCharts图表为PDF?

React Hooks + ApexCharts 动态渲染时获取图表实例导出PDF的解决方案

问题描述

使用React Hooks结合ApexCharts动态渲染图表,点击导出按钮时,通过window.ApexCharts.getChartByID无法获取图表实例(返回undefined),window.Apex._chartInstances为空数组,无法生成PDF。

核心原因

动态渲染场景下,ApexCharts的全局实例注册可能存在延迟,或者组件更新时图表ID的变更没有同步到全局实例中,导致通过全局方法无法正确获取实例。

解决方案:使用useRef直接绑定图表实例

1. 声明useRef存储图表实例

在组件内部添加ref变量,用于存储ApexCharts的实例:

import { useRef, useState, useEffect } from 'react';
import Chart from 'react-apexcharts';
import { jsPDF } from 'jspdf';

// ... 其他组件代码

const chartRef = useRef(null);

2. 给Chart组件绑定ref

将ref传递给<Chart>组件,组件渲染后就能直接获取到图表实例:

<Button
  label="Export to PDF"
  size="small"
  secondary
  onClick={handleExportPDF}
/>

<Chart
  ref={chartRef} // 绑定ref到图表组件
  options={options}
  series={options.series}
  height="500px"
  width="99%"
  type="area"
/>

3. 实现导出PDF的逻辑

通过ref获取图表实例,调用dataURI方法生成图片,再用jsPDF创建PDF:

const handleExportPDF = async () => {
  if (!chartRef.current) return;

  try {
    // 获取图表的图片URI
    const { imgURI } = await chartRef.current.dataURI();
    const pdf = new jsPDF('p', 'mm', 'a4');
    
    // 计算图片在PDF中的适配尺寸(留10%边距)
    const pageWidth = pdf.internal.pageSize.getWidth();
    const imgWidth = pageWidth * 0.9;
    const imgHeight = (imgWidth / chartRef.current.width) * chartRef.current.height;

    // 将图片添加到PDF居中位置
    pdf.addImage(imgURI, 'PNG', (pageWidth - imgWidth)/2, 20, imgWidth, imgHeight);
    pdf.save(`${options.chart.id}.pdf`);
  } catch (error) {
    console.error('导出PDF失败:', error);
  }
};

4. 多图表导出的处理

如果需要导出多个动态渲染的图表,使用数组ref存储多个实例:

// 声明数组ref存储多个图表实例
const chartRefs = useRef([]);

// 给每个图表绑定ref
{chartList.map((chartData, index) => (
  <Chart
    key={index}
    ref={el => chartRefs.current[index] = el}
    options={chartData.options}
    series={chartData.series}
    type="area"
    height="500px"
  />
))}

// 导出多个图表到同一PDF
const handleExportMultiplePDF = async () => {
  const pdf = new jsPDF('p', 'mm', 'a4');
  const pageWidth = pdf.internal.pageSize.getWidth();
  let currentY = 20;

  for (const chart of chartRefs.current) {
    if (!chart) continue;
    const { imgURI } = await chart.dataURI();
    const imgWidth = pageWidth * 0.9;
    const imgHeight = (imgWidth / chart.width) * chart.height;

    // 当前页面放不下时新增页面
    if (currentY + imgHeight > pdf.internal.pageSize.getHeight() - 20) {
      pdf.addPage();
      currentY = 20;
    }

    pdf.addImage(imgURI, 'PNG', (pageWidth - imgWidth)/2, currentY, imgWidth, imgHeight);
    currentY += imgHeight + 20; // 图表间留间距
  }

  pdf.save('multiple-charts.pdf');
};

注意事项

  • 确保调用dataURI时图表已完成渲染,可通过useEffect监听storeId变化,确认图表更新完成后再允许导出。
  • 若图表数据更新频繁,建议添加加载状态,避免在图表未渲染完成时触发导出。

内容的提问来源于stack exchange,提问作者zlobul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:26:06