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

在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");
};
解决方案

核心问题分析

  1. 数据点时间重复:所有数据点的t值都是同一个new Date(),导致所有点在x轴上完全重合,无法显示折线。
  2. 未配置时间轴:使用t字段作为时间数据,但未将x轴类型设置为time,Charts.js无法识别时间维度。
  3. 缺少时间适配器:Charts.js的时间轴依赖第三方适配器(如chartjs-adapter-date-fns),Lambda环境需安装该依赖。

修复步骤

  1. 安装必要依赖:
    在项目中安装时间适配器:
    npm install chartjs-adapter-date-fns date-fns
    
  2. 修正数据点时间:为每个数据点生成递增的时间(比如按秒递增)。
  3. 配置x轴为时间类型:在scales中添加x轴配置,指定类型为time。
  4. 规范插件配置:统一插件配置逻辑,避免重复定义。

修复后代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:30:44