如何将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
相关产品推荐
相关产品推荐

