ChartjsNodeCanvas icon indicating copy to clipboard operation
ChartjsNodeCanvas copied to clipboard

Background Image - Cannot use loadimage and resize the image

Open niveKKumar opened this issue 3 years ago • 2 comments

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 avatar May 14 '22 17:05 niveKKumar

With svg it works 👀

niveKKumar avatar May 14 '22 19:05 niveKKumar

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

SeanSobey avatar May 25 '22 00:05 SeanSobey