在AWS Lambda中使用Charts.js生成PNG图表仅显示坐标轴无数据的问题
问题
在AWS Lambda函数中使用Charts.js生成PNG图表时,仅渲染出坐标轴和背景,无数据折线显示。调用plotData([100, 200, 300, 400, 500, 1600])后,渲染结果为仅显示y轴刻度、标题、图例的空白坐标轴,无红色折线数据。
原代码如下:
export const plotData = (values: number[]): Buffer | null => { const canvas = createCanvas(800, 600); let ctx: ChartItem = canvas as unknown as ChartItem; const plugin: Plugin = { id: "customCanvasBackgroundColor", beforeDraw: (chart: any, _args: any, options: any) => { const { ctx: context } = chart; context.save(); context.globalCompositeOperation = "destination-over"; context.fillStyle = options.color || "#99ffff"; context.fillRect(0, 0, chart.width, chart.height); context.restore(); }, }; const chart = new Chart(ctx, { type: "line", data: { datasets: [ { label: "ph", data: values.map((y) => ({ y, t: new Date(), })), borderWidth: 2, borderColor: "red", backgroundColor: "rgb(255, 0, 0, 0.5)", }, ], }, options: { responsive: false, animation: false, scales: { y: { beginAtZero: true, }, }, plugins: { legend: { position: "top", }, title: { display: true, text: "TEstuibg", }, customCanvasBackgroundColor: { color: "rgba(255,255,255, 1)", }, }, }, plugins: [plugin], }); // chart.draw(); chart.update(); return canvas.toBuffer("image/png"); };
解决方案
核心问题分析
- 数据点时间重复:所有数据点的
t值都是同一个new Date(),导致所有点在x轴上完全重合,无法显示折线。 - 未配置时间轴:使用
t字段作为时间数据,但未将x轴类型设置为time,Charts.js无法识别时间维度。 - 缺少时间适配器:Charts.js的时间轴依赖第三方适配器(如
chartjs-adapter-date-fns),Lambda环境需安装该依赖。
修复步骤
- 安装必要依赖:
在项目中安装时间适配器:npm install chartjs-adapter-date-fns date-fns - 修正数据点时间:为每个数据点生成递增的时间(比如按秒递增)。
- 配置x轴为时间类型:在
scales中添加x轴配置,指定类型为time。 - 规范插件配置:统一插件配置逻辑,避免重复定义。
修复后代码
import { Chart, ChartItem, Plugin } from 'chart.js'; import { createCanvas } from 'canvas'; // 引入时间适配器 import 'chartjs-adapter-date-fns'; export const plotData = (values: number[]): Buffer | null => { const canvas = createCanvas(800, 600); const ctx = canvas.getContext('2d') as unknown as ChartItem; const chart = new Chart(ctx, { type: "line", data: { datasets: [ { label: "ph", // 生成递增的时间数据,每个点间隔1秒 data: values.map((y, index) => ({ y, t: new Date(Date.now() + index * 1000), })), borderWidth: 2, borderColor: "red", backgroundColor: "rgba(255, 0, 0, 0.5)", fill: false, // 可选:关闭填充,仅显示折线 }, ], }, options: { responsive: false, animation: false, scales: { y: { beginAtZero: true, max: Math.max(...values) * 1.1, // 可选:设置y轴最大值,避免数据超出范围 }, x: { type: 'time', // 指定x轴为时间类型 time: { unit: 'second', // 按秒显示刻度 }, title: { display: true, text: '时间', }, }, }, plugins: { legend: { position: "top", }, title: { display: true, text: "测试图表", }, customCanvasBackgroundColor: { color: "rgba(255,255,255, 1)", }, }, }, plugins: [{ id: "customCanvasBackgroundColor", beforeDraw: (chart: any, _args: any, options: any) => { const { ctx: context } = chart; context.save(); context.globalCompositeOperation = "destination-over"; context.fillStyle = options.color || "#99ffff"; context.fillRect(0, 0, chart.width, chart.height); context.restore(); }, }], }); chart.update(); return canvas.toBuffer("image/png"); };
额外注意事项
- 确保Lambda环境中已安装所有依赖(
chart.js、canvas、chartjs-adapter-date-fns、date-fns)。 - 如果不需要时间轴,可直接使用数组索引作为x值,将数据格式改为
values.map((y, x) => ({x, y})),并将x轴类型设置为linear或category。
内容的提问来源于stack exchange,提问作者Donato Azevedo
相关产品推荐
相关产品推荐

