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

如何将Chart.js+jsPDF图表集成到Node.js PDF生成流程?

集成Puppeteer与Chart.js生成带图表的PDF报告

方案一:在Puppeteer渲染的页面中直接生成Chart.js图表(推荐)

利用Puppeteer操控浏览器的特性,在目标HTML页面中嵌入Chart.js,动态注入数据渲染图表后,连同已有表格一起生成PDF,无需额外转换步骤。

步骤1:准备HTML模板(template.html)

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    table { border-collapse: collapse; width: 100%; margin: 20px 0; }
    th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
    th { background-color: #f2f2f2; }
    .chart-box { width: 90%; margin: 0 auto; height: 400px; }
  </style>
</head>
<body>
  <h2>业务数据报告</h2>
  <div id="table-wrapper"></div>
  <div class="chart-box">
    <canvas id="data-chart"></canvas>
  </div>

  <script>
    // 接收Puppeteer传入的动态数据,渲染表格和图表
    window.renderFullReport = function(reportData) {
      // 渲染表格
      const tableHtml = `
        <table>
          <thead><tr>${reportData.tableHeaders.map(h => `<th>${h}</th>`).join('')}</tr></thead>
          <tbody>${reportData.tableRows.map(row => `<tr>${row.map(cell => `<td>${cell}</td>`).join('')}</tr>`).join('')}</tbody>
        </table>
      `;
      document.getElementById('table-wrapper').innerHTML = tableHtml;

      // 渲染Chart.js图表
      const ctx = document.getElementById('data-chart').getContext('2d');
      new Chart(ctx, reportData.chartConfig);
    }
  </script>
</body>
</html>

步骤2:修改Puppeteer代码集成渲染逻辑

const puppeteer = require('puppeteer');
const fs = require('fs');

async function generateFinalReport() {
  // 动态业务数据(可从接口/数据库获取)
  const dynamicData = {
    tableHeaders: ['产品ID', '月度销量', '毛利率'],
    tableRows: [
      ['P001', 1280, '32%'],
      ['P002', 960, '28%'],
      ['P003', 1540, '35%']
    ],
    chartConfig: {
      type: 'line',
      data: {
        labels: ['1月', '2月', '3月', '4月', '5月'],
        datasets: [
          { label: 'P001销量', data: [900, 1100, 1300, 1250, 1280], borderColor: '#FF6384' },
          { label: 'P002销量', data: [700, 850, 900, 980, 960], borderColor: '#36A2EB' }
        ]
      },
      options: { responsive: true, scales: { y: { beginAtZero: true } } }
    }
  };

  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // 加载本地HTML模板
  const templateContent = fs.readFileSync('./template.html', 'utf8');
  await page.setContent(templateContent);

  // 注入数据并触发渲染
  await page.evaluate((data) => {
    window.renderFullReport(data);
  }, dynamicData);

  // 等待图表渲染完成(根据图表复杂度调整时长)
  await page.waitForTimeout(1200);

  // 生成PDF(必须开启printBackground保留图表颜色)
  await page.pdf({
    path: 'business-report.pdf',
    format: 'A4',
    printBackground: true,
    margin: { top: '20px', right: '20px', bottom: '20px', left: '20px' }
  });

  await browser.close();
  console.log('带图表的PDF报告已生成');
}

generateFinalReport();

方案二:将Chart.js图表转为图片嵌入Puppeteer PDF

适合已有成熟jsPDF图表生成逻辑的场景,先把图表转为Base64图片,再嵌入到Puppeteer的HTML内容中。

步骤1:编写图表转Base64工具函数

const { createCanvas } = require('canvas'); // 需安装依赖:npm install canvas
const Chart = require('chart.js/auto');

function chartToBase64(chartConfig) {
  const canvas = createCanvas(800, 450);
  const ctx = canvas.getContext('2d');
  new Chart(ctx, chartConfig);
  return canvas.toDataURL('image/png');
}

步骤2:修改Puppeteer代码嵌入图片

const puppeteer = require('puppeteer');
const chartToBase64 = require('./chart-utils');

async function generateReportWithImageChart() {
  // 动态数据
  const tableData = {
    headers: ['区域', '客户数', '销售额'],
    rows: [['华东', 240, '¥128万'], ['华南', 180, '¥96万'], ['华北', 150, '¥82万']]
  };
  const chartConfig = {
    type: 'pie',
    data: {
      labels: ['华东', '华南', '华北'],
      datasets: [{ data: [128, 96, 82], backgroundColor: ['#FFCE56', '#4BC0C0', '#9966FF'] }]
    }
  };

  // 生成图表Base64图片
  const chartImage = chartToBase64(chartConfig);

  // 构建包含表格和图片的HTML
  const htmlContent = `
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        table { border-collapse: collapse; width: 100%; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 8px; }
        .chart-img { display: block; margin: 0 auto; width: 80%; }
      </style>
    </head>
    <body>
      <h2>区域销售报告</h2>
      <table>
        <thead><tr>${tableData.headers.map(h => `<th>${h}</th>`).join('')}</tr></thead>
        <tbody>${tableData.rows.map(row => `<tr>${row.map(cell => `<td>${cell}</td>`).join('')}</tr>`).join('')}</tbody>
      </table>
      <img src="${chartImage}" class="chart-img" alt="区域销售占比">
    </body>
    </html>
  `;

  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setContent(htmlContent);

  await page.pdf({
    path: 'region-sales-report.pdf',
    format: 'A4',
    printBackground: true
  });

  await browser.close();
}

generateReportWithImageChart();

关键注意事项

  • 方案一中必须开启printBackground: true,否则图表的颜色、背景会丢失。
  • 方案二需要安装canvas包,用于在Node.js环境模拟浏览器Canvas生成图表。
  • 若图表数据量大或渲染复杂,方案一中需适当延长waitForTimeout的时长,确保图表完全渲染。
  • 动态数据需严格匹配模板中的格式要求,比如表格行需为二维数组,图表配置需符合Chart.js官方规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:18:20