Open almeidx opened 1 year ago
Same issue here
I am still using CommonJS and was able to upgrade to Chart.js 4.2.0 successfully. I do not have an overly complicated project and the only breaking change I ran into (proving the upgrade did work since it was a break in my code) was:
scales[id].grid.drawBorder has been renamed to scales[id].border.display.
The release notes note that dist/chart.js is now an ESM only module and the dist/chart.min.js is now dist/chart.umd.js.
Update: I was doing testing with Node.js 18 and did a a fresh install of node_modules in a test project root. At that point, I was no longer able to run Chart.js 4.2.0. Had me very puzzled. Then I realized I had been working with a modified copy of dist/index.js where I had modified the require statement at line 149 to read require("chart.js/auto"), which was a fix I noted in issue #118 . Forgot I had left it in. Putting that back in and the Chart.js 4.2.0 install now works. I have no plans to migrate to 4.x.x any time soon but I was able to catalog the breaking changes in it for future refefence.
At the root of my project I did (at the time) npm install @.*** The current version is now 4.3.0 so would replace 4.2.0 with 4.3.0.
I am not sure why your initialization is failing. As part of my code, I created my own plugin that I register with the following code:
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height, backgroundColour: "white", chartCallback: (ChartJS) => { ChartJS.register(require("chartjs-plugin-datalabels")); } });
This is working with Chart.js 4.2.0 installed in my project. The only difference I ran into between 3.x and 4.x with my project was the property x.grid.drawBorder being replaced by x.border.display. The fact that the former does not work was verification that my code was calling 4.2.0.
On Mon, May 1, 2023 at 6:25 PM sharq88 @.***> wrote:
@Whobeu https://github.com/Whobeu I don't know how did you manage to upgrade... I tried with a bare minimum-ish code:
const { ChartJSNodeCanvas } = require('chartjs-node-canvas'); const chartJSNodeCanvas = new ChartJSNodeCanvas({ width:400, height:400, backgroundColour:'white'});
(async () => { const configuration = { type: 'line', data: { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [{ label: 'My First Dataset', data: [65, 59, 80, 81, 56, 55, 40] }] } }; const dataUrl = await chartJSNodeCanvas.renderToDataURL(configuration); console.log(dataUrl); })();
which gives:
TypeError: chartJs.register is not a function at ChartJSNodeCanvas.initialize (../node_modules/chartjs-node-canvas/dist/index.js:182:21)
I'd appreciate any help/guide on how to get this working!
— Reply to this email directly, view it on GitHub https://github.com/SeanSobey/ChartjsNodeCanvas/issues/121#issuecomment-1530442291, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB5K2ASHUFXAQLYCDBHQJYLXEAZ53ANCNFSM6AAAAAASR2AX6I . You are receiving this because you were mentioned.Message ID: @.***>
The code has to be changed from
const chartJs = require('chart.js');
to
const chartJs = require('chart.js/auto');
Unfortunately looks like the project is dead
chartjs-node-canvas
doesn't support chart.js@4
. However, you can simply use the canvas
library instead. Here is an example for your reference.
Filename: make-image.js
const { createCanvas, registerFont } = require('canvas');
const Chart = require('chart.js/auto');
// Create a canvas and chart
const width = 800;
const height = 400;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');
const chartConfig = {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [
{
label: 'My First Dataset',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ['red', 'blue', 'yellow', 'green', 'purple', 'orange'],
},
],
},
options: {
responsive: false,
maintainAspectRatio: false,
},
};
new Chart(ctx, chartConfig);
// Save the chart image as a file
const fs = require('fs');
const out = fs.createWriteStream('chart.png');
const stream = canvas.createPNGStream();
stream.pipe(out);
out.on('finish', () => console.log('The chart image was saved.'));
Then, run the script via node. A image named chart.png
will be generated.
➜ node make-image.js
The chart image was saved.
➜ ls -l chart.png
-rw-r--r-- 1 user1 admin 13K Nov 4 20:02 chart.png
The code is tested with chart.js@4.4.0
and canvas@2.11.2
in node@20.4.0
.
chartjs-node-canvas
doesn't supportchart.js@4
. However, you can simply use thecanvas
library instead. Here is an example for your reference.Filename: make-image.js
const { createCanvas, registerFont } = require('canvas'); const Chart = require('chart.js/auto'); // Create a canvas and chart const width = 800; const height = 400; const canvas = createCanvas(width, height); const ctx = canvas.getContext('2d'); const chartConfig = { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [ { label: 'My First Dataset', data: [12, 19, 3, 5, 2, 3], backgroundColor: ['red', 'blue', 'yellow', 'green', 'purple', 'orange'], }, ], }, options: { responsive: false, maintainAspectRatio: false, }, }; new Chart(ctx, chartConfig); // Save the chart image as a file const fs = require('fs'); const out = fs.createWriteStream('chart.png'); const stream = canvas.createPNGStream(); stream.pipe(out); out.on('finish', () => console.log('The chart image was saved.'));
Then, run the script via node. A image named
chart.png
will be generated.➜ node make-image.js The chart image was saved. ➜ ls -l chart.png -rw-r--r-- 1 user1 admin 13K Nov 4 20:02 chart.png
The code is tested with
chart.js@4.4.0
andcanvas@2.11.2
innode@20.4.0
.
I have been able to get some rudimentary image generation doing the above in an existing project. I have a rather complicated graphing routine that uses several features of ChartjsNodeCanvas so it is a bit involved moving over to pure Canvas and Chart.js. As an example, I set a background color on my image using the ChartjsNodeCanvas "backgroundColour" property. However, that does not exist in either Chart.js or Canvas so it requires implementing the "beforeDraw" event myself to do it. Also finding some other minor features that appear will require my own implementation. Long term this is probably the best solution to keep up with newer releases to Chart.js.
The code has to be changed from
const chartJs = require('chart.js');
to
const chartJs = require('chart.js/auto');
Unfortunately looks like the project is dead
I am starting to agree. I can't find any good alternative either.
The code has to be changed from
const chartJs = require('chart.js');
to
const chartJs = require('chart.js/auto');
Unfortunately looks like the project is dead
I am starting to agree. I can't find any good alternative either.
The best alternative is to do what @cwtuan documented above and switch to Canvas and Chart.js directly. It took a little work but I was able to replicate the functionality of ChartJsNodeCanvas that I needed using Canvas and Chart.js directly. The issues I ran into were needing to add the maintainAspectRatio option, having to create a tiny plugin to set the canvas background color and needing to wrap canvas.toBuffer() and canvas.toDataURL in Promises within my code. Otherwise implementation was very easy. I also duplicate my projects in Typescript as a sanity check and the only issue I had was passing Canvas context to Chart instantiation:
const ctx = canvas.getContext("2d");
const chart = new Chart(ctx as unknown as ChartItem, configuration);
Chart refuses to accept the context as any of the ChartItem types so I had to cast it to "unknown" and then to ChartItem. It works but Typescript has a fit with the current type definitions.
At this point I am free to upgrade to newer releases of Canvas or Chart.js as needed.
The best alternative
I have tried that, but have so many issues it (using nextjs and it really does not get along with canvas). I keep getting this error
error - Error: The specified procedure could not be found.
\\?\C:\Users\......\node_modules\canvas\build\Release\canvas.node
code: 'ERR_DLOPEN_FAILED',
Have tried so many different things, which is why I am just on the hunt for something else sadly. I really do like chartjs and may give it a few more hours of trial and error to see if I can get it to work
EDIT: Fixed the issue via solution here: https://github.com/Automattic/node-canvas/issues/2152
Thanks so much for all the discussion here it really helped me a lot. Just wanted to share what is working really well for me. It's a compilation of a lot the suggestions above.
"node": "21.7.3"
"typescript": "5.4.4"
"chart.js": "4.4.2"
"canvas": "2.11.2"
import { Chart } from "chart.js/auto";
import { createCanvas } from "canvas";
import * as fs from "node:fs";
import { ChartConfiguration } from "chart.js";
export function generateChart(): string {
const width = 800;
const height = 400;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext("2d") as unknown as CanvasRenderingContext2D;
const chartConfig: ChartConfiguration = {
type: "bar",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "My First Dataset",
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
"red",
"blue",
"yellow",
"green",
"purple",
"orange",
],
},
],
},
options: {
responsive: false,
maintainAspectRatio: false,
},
};
new Chart(ctx, chartConfig);
const buffer = canvas.toBuffer("image/png");
fs.writeFileSync("images/test-chart.png", buffer);
return "test-chart.png";
}
Just upgrading the dependency doesn't seem to be working (in ESM environments, at least)