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

无浏览器Node.js环境下,如何生成柱状图并插入PDF?

问题描述

我有一个使用PDF生成器的Node.js项目,需要在其中插入柱状图,但项目运行在无桌面环境的服务器上。请问有没有无需依赖Web浏览器,就能在Node.js运行时生成柱状图图片并插入PDF的库或方法?

我目前使用Puppeteer生成PDF,但Chart.js库无法渲染canvas,示例代码如下:

await page.setContent(`<!DOCTYPE html>
<html><body>
<canvas id="chart"></canvas>
<script>
    const ctx = document.getElementById('chart');

    new Chart(ctx, {
        type: 'bar',
        data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
            datasets: [{
                label: '# of Votes',
                data: [12, 19, 3, 5, 2, 3],
                borderWidth: 1
            }]
        },
        options: {
            scales: { y: { beginAtZero: true } }
        }
    });
</script>
</body></html>`,
{ waitUntil: 'domcontentloaded' });

await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/chart.js' })

结果显示空白页面,因此我希望找到更好的方案直接生成图片并插入。

我还尝试了以下代码:

await page.setContent(`<!DOCTYPE html>
<html><body>
<canvas id="chart"></canvas>
</body></html>`,
{ waitUntil: [ 'load', 'networkidle0' ] });

await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/chart.js' });
await page.addScriptTag({ content: `
    const ctx = document.getElementById('chart');

    new Chart(ctx, {
        type: 'bar',
        data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
            datasets: [{
                label: '# of Votes',
                data: [12, 19, 3, 5, 2, 3],
                borderWidth: 1
            }]
        },
        options: {
            scales: { y: { beginAtZero: true } }
        }
    });
});

解决方案

方案一:node-canvas + Chart.js(无浏览器依赖)

直接在Node.js环境生成Canvas图片,完全不需要浏览器支持,适合无桌面环境的服务器。

  1. 安装依赖:
npm install canvas chart.js
  1. 示例代码:
const { createCanvas } = require('canvas');
const Chart = require('chart.js/auto');
const fs = require('fs');
const PDFDocument = require('pdfkit');

// 创建固定尺寸的画布
const canvas = createCanvas(800, 600);
const ctx = canvas.getContext('2d');

// 生成柱状图
new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            borderWidth: 1,
            backgroundColor: ['#ff6384', '#36a2eb', '#ffce56', '#4bc0c0', '#9966ff', '#ff9f40']
        }]
    },
    options: {
        responsive: false, // 固定画布尺寸,关闭响应式
        scales: { y: { beginAtZero: true } }
    }
});

// 将画布转为PNG Buffer
const chartBuffer = canvas.toBuffer('image/png');

// 插入到PDF
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream('output.pdf'));
// 设置图片在PDF中的位置和宽度
doc.image(chartBuffer, 50, 50, { width: 600 });
doc.end();

方案二:修复Puppeteer + Chart.js的渲染问题

你的代码空白是因为两个问题:Canvas未指定尺寸、Chart.js加载和执行顺序错误。修改后的代码如下:

await page.setContent(`<!DOCTYPE html>
<html><body>
<!-- 必须指定Canvas的宽高 -->
<canvas id="chart" width="800" height="600"></canvas>
</body></html>`, { waitUntil: 'networkidle0' });

// 先加载Chart.js库
await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/chart.js' });

// 等待库加载完成后,执行图表渲染逻辑
await page.evaluate(() => {
    const ctx = document.getElementById('chart').getContext('2d');
    new Chart(ctx, {
        type: 'bar',
        data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
            datasets: [{
                label: '# of Votes',
                data: [12, 19, 3, 5, 2, 3],
                borderWidth: 1
            }]
        },
        options: {
            scales: { y: { beginAtZero: true } }
        }
    });
});

// 等待图表渲染完成(可根据实际情况调整延迟时间)
await page.waitForTimeout(1000);

// 生成PDF
await page.pdf({ path: 'output.pdf', format: 'A4' });

方案三:使用chartjs-node-canvas(封装好的工具)

这是专门为Node.js环境封装的Chart.js工具,简化了node-canvas的配置步骤。

  1. 安装依赖:
npm install chartjs-node-canvas pdfkit
  1. 示例代码:
const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
const fs = require('fs');
const PDFDocument = require('pdfkit');

// 定义图表尺寸
const chartWidth = 800;
const chartHeight = 600;
const chartCanvas = new ChartJSNodeCanvas({ width: chartWidth, height: chartHeight });

(async () => {
    // 生成图表图片Buffer
    const chartBuffer = await chartCanvas.renderToBuffer({
        type: 'bar',
        data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
            datasets: [{
                label: '# of Votes',
                data: [12, 19, 3, 5, 2, 3],
                borderWidth: 1
            }]
        },
        options: {
            scales: { y: { beginAtZero: true } }
        }
    });

    // 插入到PDF
    const doc = new PDFDocument();
    doc.pipe(fs.createWriteStream('output.pdf'));
    doc.image(chartBuffer, 50, 50, { width: 600 });
    doc.end();
})();

内容的提问来源于stack exchange,提问作者e-info128

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:15:33