SeanSobey / ChartjsNodeCanvas

A node renderer for Chart.js using canvas.
MIT License
228 stars 70 forks source link

Background Image - Cannot use loadimage and resize the image #103

Open niveKKumar opened 2 years ago

niveKKumar commented 2 years ago

I am trying to load a local image and draw it to my background of my chart. Problem is, it doesnt resize and keeps the original width. Any idea why is that ?

const img = await loadImage(path);
const chartJSNodeCanvas = new ChartJSNodeCanvas({
    // backgroundColour: "#2f3136",
    width: 1000,
    height: 1000,
    chartCallback(c) {
      c.register({
        id: "logo",
        beforeDraw(chart) {
          const canvas = chart.canvas;
          const ctx = chart.canvas.getContext("2d");
          ctx.save();
          ctx.fillStyle = "#2f3136";
          const w = canvas.width;
          const h = canvas.height;
          ctx.fillRect(0, 0, w, h);
          ctx.globalAlpha = 0.15;
          const faktor = 1;
          img.width = w / faktor;
          img.height = h / faktor;
          ctx.drawImage(
            img as any,
            (canvas.width - img.width) / 2,
            (canvas.height - img.height) / 2,
            img.width,
            img.height
          );
          ctx.restore();
        },
      });
    },
    .
  });

With faktor 1 it should be as big as my canvas. My file has the size 500x500 which it keeps In addition it seems that drawImage only allows HTMLImageElement, which as far I am aware of you, you cant create with a pure node project

niveKKumar commented 2 years ago

With svg it works 👀

SeanSobey commented 2 years ago

Hi there!

This works fine for me:

const { ChartJSNodeCanvas } = require('./index');
const { loadImage } = require('canvas');
const fs = require('fs/promises');

async function main() {

    const width = 400;
    const height = 400;
    const configuration = {
        type: 'bar',
        data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
            datasets: [{
                label: '# of Votes',
                data: [12, 19, 3, 5, 2, 3],
                backgroundColor: [
                    'rgba(255, 99, 132, 0.2)',
                    'rgba(54, 162, 235, 0.2)',
                    'rgba(255, 206, 86, 0.2)',
                    'rgba(75, 192, 192, 0.2)',
                    'rgba(153, 102, 255, 0.2)',
                    'rgba(255, 159, 64, 0.2)'
                ],
                borderColor: [
                    'rgba(255,99,132,1)',
                    'rgba(54, 162, 235, 1)',
                    'rgba(255, 206, 86, 1)',
                    'rgba(75, 192, 192, 1)',
                    'rgba(153, 102, 255, 1)',
                    'rgba(255, 159, 64, 1)'
                ],
                borderWidth: 1
            }]
        }
    };
    const buf = await fs.readFile('./banana.jpg');
    const img = await loadImage(buf);
    const chartJSNodeCanvas = new ChartJSNodeCanvas({
        width, height,
        chartCallback(c) {
            c.register({
                id: "logo",
                beforeDraw(chart) {
                    const canvas = chart.canvas;
                    const ctx = chart.canvas.getContext("2d");
                    ctx.save();
                    ctx.globalAlpha = 0.5;
                    const scale = Math.max(canvas.width / img.width, canvas.height / img.height);
                    // get the top left position of the image
                    const x = (canvas.width / 2) - (img.width / 2) * scale;
                    const y = (canvas.height / 2) - (img.height / 2) * scale;
                    ctx.drawImage(img, x, y, img.width * scale, img.height * scale);
                    ctx.restore();
                },
            });
        }
    });
    const buffer = await chartJSNodeCanvas.renderToBuffer(configuration);
    await fs.writeFile('./test.png', buffer, 'base64');
}

main();

test

Looks like you are using canvas.drawImage incorrectly.

Also, note the use of node-canvas's loadimage, my apologies, the integration of this lib is not obvious enough and a constant source of issues. I hope to make this more intuitive going forward