将 Chart.js 图表导出为 Base64 图片并嵌入 PDF

6次阅读

本文介绍如何将 Chart.js 渲染的 canvas 图表转换为 Base64 PNG 图像,并在 HTML 中动态替换为 ,从而确保使用 pdfkit 等工具生成 PDF 时图表可见、清晰且可复现。

本文介绍如何将 chart.js 渲染的 canvas 图表转换为 base64 png 图像,并在 html 中动态替换为 `将 Chart.js 图表导出为 Base64 图片并嵌入 PDF`,从而确保使用 pdfkit 等工具生成 pdf 时图表可见、清晰且可复现。

在 Web 应用中使用 Chart.js 创建交互式图表非常便捷,但当需将含图表的 HTML 页面导出为 PDF(例如通过 pdfkit.from_file())时,常遇到图表“丢失”的问题——这是因为 pdfkit 基于无头浏览器(如 wkhtmltopdf)渲染 HTML,不执行 JavaScript,也无法解析动态绘制的 内容。Canvas 是纯客户端绘制的位图,未被转为静态图像前,PDF 工具无法捕获其内容。

解决该问题的核心思路是:在页面加载完成、图表渲染完毕后,立即将 Canvas 转换为 Base64 编码的 PNG 图像,并用 将 Chart.js 图表导出为 Base64 图片并嵌入 PDF 标签替代原 元素。这样,HTML 文件在保存或打印时即包含静态图像资源,完全规避 JS 执行依赖。

✅ 实现步骤详解

1. 利用 Chart.js 的 animation.onComplete 钩子触发转换

Chart.js 提供了可靠的生命周期钩子 animation.onComplete,确保图表完全绘制完成后再执行图像导出逻辑:

options: {   animation: {     onComplete: function() {       const canvas = document.getElementById('ndvi_evi_chart');       const base64Image = canvas.toDataURL('image/png'); // 默认质量 0.92,支持 'image/jpeg' 及 quality 参数       document.getElementById('canvas-as-image').innerHTML =          `@@##@@`;     }   },   // ...其余配置保持不变 }

⚠️ 注意:toDataURL() 要求 Canvas 已完成渲染,且不能处于跨域污染状态(即所有图表资源/图片需同源或启用 CORS)。若使用自定义图标或外部字体,请确保其加载完成后再初始化图表(可配合 promise.all() 或 chart.render() 后置调用)。

2. HTML 结构适配:保留 canvas + 容器用于插入图片

修改 dom 结构,为图像预留容器,并隐藏原始 canvas(尤其在打印/PDF 场景下):

<div class="chartNdvi" style="border:1px solid #A9A9A9">   <p style="font-weight: bold; font-size:15px;">Crop Health</p>   <p style="font-size:10px;">NDVI and EVI (Six Month Historical Data)</p>   <canvas id="ndvi_evi_chart" width="500" height="200"></canvas>   <div id="canvas-as-image" aria-hidden="true"></div> </div>

✨ 提示:建议将 尺寸设为合理值(如 width=”500″ height=”200″),避免因默认尺寸过小导致图像模糊;Base64 图像会自动按容器缩放,但原始分辨率越高,PDF 中越清晰。

3. (可选)增强打印兼容性:CSS 媒体查询控制显隐

为兼顾屏幕浏览与 PDF 导出体验,可通过 CSS 媒体查询智能切换显示元素:

/* 屏幕模式:显示 canvas,隐藏图片 */ @media screen {   #ndvi_evi_chart { display: block; }   #canvas-as-image { display: none; } }  /* 打印/PDF 模式:隐藏 canvas,显示图片 */ @media print {   #ndvi_evi_chart { display: none; }   #canvas-as-image { display: block; } }

启用后,用户直接浏览器打印或 pdfkit 渲染时,将自动使用 将 Chart.js 图表导出为 Base64 图片并嵌入 PDF;开发者调试时仍可见可交互的 Canvas。

4. Python 端:确保 PDF 生成无额外干预

pdfkit.from_file() 默认模拟打印行为(即触发 @media print),因此只要 HTML 中已注入 Base64 图像,无需修改 Python 代码:

import pdfkit pdfkit.from_file('144474.html', 'output1.pdf',                   options={'page-size': 'A4', 'margin-top': '0.5in'})

✅ 输出 PDF 将包含清晰、抗锯齿的图表图像,且无需额外服务端截图(如 Puppeteer),轻量可靠。

? 补充说明与最佳实践

  • Base64 图像体积:PNG 格式对图表压缩友好,但大量图表可能增加 HTML 体积。如需极致优化,可考虑生成后端截图(Puppeteer)或导出 SVG(Chart.js v4+ 支持 plugins: { decimation: false } + 自定义 renderer,但复杂度高)。
  • 字体一致性:Chart.js 默认使用系统字体。若 PDF 中文字样式异常,建议在 options.plugins.legend.labels.font 等处显式指定 ‘Arial’, ‘sans-serif’ 等安全字体。
  • 多图表批量处理:可封装通用函数,遍历所有 .chart-container 并绑定 onComplete 逻辑,提升可维护性。

通过这一方案,你不仅解决了 PDF 导出的图表缺失问题,还构建了一套前端驱动、零依赖、高兼容性的可视化交付流程——让数据洞察真正“所见即所得”。

将 Chart.js 图表导出为 Base64 图片并嵌入 PDF

text=ZqhQzanResources