I'm trying to export a chart created with chartjs without an actual site it's just a node backend app that creates the chart, I then need to export it and send it to slack api.
I figured I would try to create a virtual dom and then export from there but is it not working. I'm open to other approaches or fixes to this code. I'm getting an error that says window is undefined, but if I console.log(window) it says it's a window object, and everything looks normal.
const JSDOM = require("jsdom");
const Chart = require("chart.js");
const dom = new JSDOM.JSDOM(`<!DOCTYPE html><canvas id="myChart" width="400" height="400"></canvas>`);
const canvas = dom.window.document.getElementById('myChart');
const ctx = canvas.getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Standing costs', 'Running costs'],
datasets: [{
label: 'Washing and cleaning',
data: [0, 8],
backgroundColor: '#22aa99'
}, {
label: 'Traffic tickets',
data: [0, 2],
backgroundColor: '#994499'
}, {
label: 'Tolls',
data: [0, 1],
backgroundColor: '#316395'
}, {
label: 'Parking',
data: [5, 2],
backgroundColor: '#b82e2e'
}, {
label: 'Car tax',
data: [0, 1],
backgroundColor: '#66aa00'
}, {
label: 'Repairs and improvements',
data: [0, 2],
backgroundColor: '#dd4477'
}, {
label: 'Maintenance',
data: [6, 1],
backgroundColor: '#0099c6'
}, {
label: 'Inspection',
data: [0, 2],
backgroundColor: '#990099'
}, {
label: 'Loan interest',
data: [0, 3],
backgroundColor: '#109618'
}, {
label: 'Depreciation of the vehicle',
data: [0, 2],
backgroundColor: '#109618'
}, {
label: 'Fuel',
data: [0, 1],
backgroundColor: '#dc3912'
}, {
label: 'Insurance and Breakdown cover',
data: [4, 0],
backgroundColor: '#3366cc'
}]
},
options: {
onAnimationComplete: animationDone,
responsive: false,
legend: {
position: 'right'
},
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
function animationDone() {
return canvas.toDataUrl("image/jpg");
}
I just want an image file or url that I can send to slack api.
Use chartjs-node-canvas, this is a Node JS renderer for Chart.js using canvas.
It provides and alternative to chartjs-node that does not require jsdom (or the global variables that this requires) and allows chartJS as a peer dependency, so you can manage its version yourself.
This is how it will work with your code:
const { CanvasRenderService } = require('chartjs-node-canvas');
const width = 400;
const height = 400;
const chartCallback = (ChartJS) => {
// Global config example: https://www.chartjs.org/docs/latest/configuration/
ChartJS.defaults.global.elements.rectangle.borderWidth = 2;
// Global plugin example: https://www.chartjs.org/docs/latest/developers/plugins.html
ChartJS.plugins.register({
// plugin implementation
});
// New chart type example: https://www.chartjs.org/docs/latest/developers/charts.html
ChartJS.controllers.MyType = ChartJS.DatasetController.extend({
// chart implementation
});
};
const canvasRenderService = new CanvasRenderService(width, height, chartCallback);
(async () => {
const configuration = {
type: 'line',
data: {
labels: ['Standing costs', 'Running costs'],
datasets: [{
label: 'Washing and cleaning',
data: [0, 8],
backgroundColor: '#22aa99'
}, {
label: 'Traffic tickets',
data: [0, 2],
backgroundColor: '#994499'
}, {
label: 'Tolls',
data: [0, 1],
backgroundColor: '#316395'
}, {
label: 'Parking',
data: [5, 2],
backgroundColor: '#b82e2e'
}, {
label: 'Car tax',
data: [0, 1],
backgroundColor: '#66aa00'
}, {
label: 'Repairs and improvements',
data: [0, 2],
backgroundColor: '#dd4477'
}, {
label: 'Maintenance',
data: [6, 1],
backgroundColor: '#0099c6'
}, {
label: 'Inspection',
data: [0, 2],
backgroundColor: '#990099'
}, {
label: 'Loan interest',
data: [0, 3],
backgroundColor: '#109618'
}, {
label: 'Depreciation of the vehicle',
data: [0, 2],
backgroundColor: '#109618'
}, {
label: 'Fuel',
data: [0, 1],
backgroundColor: '#dc3912'
}, {
label: 'Insurance and Breakdown cover',
data: [4, 0],
backgroundColor: '#3366cc'
}]
},
options: {
responsive: false,
legend: {
position: 'right'
},
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
};
const dataUrl = await canvasRenderService.renderToDataURL(configuration);
})();
dataUrl variable will contain the image you can pass to Slack API
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With