如何用TCPDF生成包含ECharts的PDF?现有方案遇阻求解决
生成含ECharts的PDF可行方案
方案1:ECharts转Base64图片,通过AJAX传给PHP生成PDF
这是兼容性最好的方案,避开TCPDF对复杂HTML/SVG的渲染缺陷:
- 前端:用ECharts内置的
getDataURL方法把图表转成base64格式图片// 初始化ECharts实例 const myChart = echarts.init(document.getElementById('chart-container')); myChart.setOption(option); // 传入你的图表配置 // 延迟确保图表渲染完成,根据复杂度调整时长 setTimeout(() => { const chartBase64 = myChart.getDataURL({ pixelRatio: 2, // 提高图片清晰度 backgroundColor: '#fff' }); // AJAX传递给PHP后端 fetch('generate-pdf.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `chart_img=${encodeURIComponent(chartBase64)}` }).then(res => res.json()).then(data => { window.open(data.pdf_url); // 打开生成的PDF }); }, 500); - 后端PHP(generate-pdf.php):接收base64并生成PDF
require_once('tcpdf/tcpdf.php'); // 解析前端传来的base64图片 $chartBase64 = urldecode($_POST['chart_img']); $chartBase64 = str_replace('data:image/png;base64,', '', $chartBase64); $chartData = base64_decode($chartBase64); // 生成临时图片文件 $tempFile = tempnam(sys_get_temp_dir(), 'echart_') . '.png'; file_put_contents($tempFile, $chartData); // 初始化TCPDF并插入图片 $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $pdf->AddPage(); $pdf->Image($tempFile, 10, 10, 190, 0, 'PNG', '', '', true, 300); // 输出PDF到服务器,或直接下载(将'F'改为'D') $pdfFileName = 'echart_report_' . time() . '.pdf'; $pdf->Output($pdfFileName, 'F'); // 返回PDF链接给前端 echo json_encode(['pdf_url' => $pdfFileName]); // 清理临时文件 unlink($tempFile);
方案2:用无头浏览器渲染完整页面生成PDF
适合需要多图表或复杂页面布局的场景,渲染效果最接近浏览器:
- 步骤1:编写包含ECharts的HTML页面(chart-page.html)
<!DOCTYPE html> <html> <head> <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script> </head> <body> <div id="chart-container" style="width: 800px; height: 600px;"></div> <script> const myChart = echarts.init(document.getElementById('chart-container')); myChart.setOption({ title: { text: 'ECharts 报表' }, xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ type: 'bar', data: [120, 200, 150, 80, 70, 110, 130] }] }); // 标记图表渲染完成 setTimeout(() => { window.__chartReady = true; }, 500); </script> </body> </html> - 步骤2:Node.js脚本(generate-pdf.js)用Puppeteer生成PDF
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('file://' + __dirname + '/chart-page.html', { waitUntil: 'networkidle0' }); // 等待图表渲染完成 await page.waitForFunction('window.__chartReady === true'); // 生成PDF await page.pdf({ path: 'echart_report.pdf', format: 'A4', printBackground: true // 保留背景色和样式 }); await browser.close(); })(); - 步骤3:PHP调用Node脚本(可选)
// 执行Node脚本生成PDF exec('node generate-pdf.js', $output, $exitCode); if ($exitCode === 0) { // 输出PDF供下载 header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="echart_report.pdf"'); readfile('echart_report.pdf'); } else { echo 'PDF生成失败'; }
方案3:优化SSR生成的SVG兼容性(适配原有尝试)
如果坚持用ECharts SSR生成SVG,需处理TCPDF不支持的SVG特性:
- 前端用ECharts SSR生成SVG字符串,通过AJAX传给PHP
- PHP用SVG处理库(如SimpleSVG)预处理SVG,移除TCPDF不支持的标签(如
<clipPath>)或属性 - 将预处理后的SVG转成图片,再用TCPDF的
Image方法插入;或尝试用TCPDF的ImageSVG方法直接嵌入(注意复杂图表仍可能出现渲染问题)
内容的提问来源于stack exchange,提问作者mikeardy
相关产品推荐
相关产品推荐

