Skip to content

How to generate chart image in Node.js environment?

Jae Sung Park edited this page Apr 23, 2021 · 5 revisions

This guide explains on how to generate chart screenshot image in Node.js environment.

1. Preparation

Basically, most of functionality will depends on Puppeteer. Install puppeteer first.

$ npm i puppeteer --save-dev

2. Create screenshot module file

// screen.mjs
import puppeteer from "puppeteer";

/**
 * Generate chart image screenshot
 * @param {object} options billboard.js generation option object
 * @param {string} path screenshot image full path with file name
 */
export default async function screenshot(options = {}, path = "chart.png") {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    // load billboard.js assets from CDN
    await page.addStyleTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css" }); 
    await page.addScriptTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js" }); 
    
    await page.evaluate(options => {
        bb.generate(options);
    }, options);

    const content = await page.$(".bb");

    // https://pptr.dev/#?product=Puppeteer&show=api-pagescreenshotoptions
    await content.screenshot({
         path,
        omitBackground: true
    });

    await page.close();
    await browser.close();
}

3. Usage

// index.mjs
import screenshot from "./screen.mjs";

await screenshot({
    data: {
        columns: [
            ["data1", 300, 350, 300, 0, 0, 0],
            ["data2", 130, 100, 140, 200, 150, 50]
        ],
        types: {
            data1: "area-step",
            data2: "area-spline"
        }
    },

    // IMPORTANT:
    // Specify 'transition.duration=0' to avoid partial rendering
    // caused by the transition(animation).
    transition: {
        duration: 0
    }
}, "./chart01.png");

await screenshot({
    data: {
        columns: [
            ["data1", 300, 350, 300, 0, 0, 0],
            ["data2", 130, 100, 140, 200, 150, 50]
        ],
        types: {
            data1: "bar",
            data2: "area"
        }
    },
    transition: {
        duration: 0
    }
}, "./chart02.png");

4. Run

$ node index.mjs
# ==> will generate 'chart01.png' and 'chart02.png'