chartjs / chartjs/chartjs-plugin-datalabels
[BUG] Weird behavior with labels
- Dominant language
- JavaScript
- Stars
- 920
- Forks
- 507
- PR merge metrics
- No merged PRs in 30d
Description
Hello,
I experienced a really weird behavior with my labels and don't know why. Im using this package in combination with `chartjs-node-canvas`.
## Description
The provided example code has three different for loop heads which work/don't work.
```ts
// run only for top=60 => perfect result
for (let top = 60; top <= 60; top += 5) {
// run a few values for top more => only a few bad
for (let top = 40; top < 70; top += 5) {
// run from 0 to 100 in 5er steps => everything bad
for (let top = 0; top < 100; top += 5) {
```
The weird part is, that it works if the for loop only runs one iteration. If it runs only a few iterations, it's sometimes correct and if its runs 20 iterations nothing is correct.
## Screenshots
Correct:

Wrong:

Look at the placement of the labels. In the correct one, the labels are placed ontop of the bars, in the wrong one they are wrapped somehow.
## Steps to reproduce
1. Create a folder and add the example code provided below
2. Create a folder next to the `index.ts` file called `a`.
3. Run the file with `npx ts-node index.ts` and try all 3 for heads. (Remember to remove all files in `a/` first to have no conflicts)
4. Compare the results
Example code
`package.json`:
```json
{
"name": "typescript-node",
"version": "1.0.0",
"scripts": {},
"dependencies": {
"@types/node": "14.14.29",
"ts-node": "9.1.1",
"typescript": "4.1.5",
"chart.js": "^3.9.1",
"chartjs-node-canvas": "^4.1.6",
"chartjs-plugin-datalabels": "^2.2.0"
}
}
```
```ts
import { ChartJSNodeCanvas } from "chartjs-node-canvas";
import { ChartConfiguration } from "chart.js";
import "chartjs-plugin-datalabels"; // to fix types
import { writeFileSync } from "fs";
const abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const srcData = new Array(100)
.fill(0)
.map((_, i) => ({ x: abc[i % (abc.length - 1)], y: i }));
(async () => {
// run only for top=60 => perfect result
// for (let top = 60; top <= 60; top += 5) {
// run a few values for top more => only a few bad
for (let top = 40; top < 70; top += 5) {
// run from 0 to 100 in 5er steps => everything bad
// for (let top = 0; top < 100; top += 5) {
const sliced = srcData.slice(0, top);
// import via require as it doesnt work otherwise
// eslint-disable-next-line @typescript-eslint/no-var-requires
const ChartDataLabels = require("chartjs-plugin-datalabels");
const scale = 2;
const chartRenderer = new ChartJSNodeCanvas({
width: scale * Math.max(400, 40 * sliced.length),
height: scale * 400,
chartCallback: async (ChartJS) => {
ChartJS.register(ChartDataLabels);
},
});
const chart: ChartConfiguration = {
type: "bar",
data: {
labels: sliced.map((x) => x.x),
datasets: [
{
label: "ABC",
data: sliced.map((x) => x.y * 2),
backgroundColor: "#f43543",
datalabels: {
labels: {
relative: {
align: "end",
anchor: "end",
color: "#ffffff",
offset: scale * 12,
font: {
size: scale * 10,
weight: "bold",
},
formatter: (_value, ctx) =>
`${~~(sliced[ctx.dataIndex].y * 10 ** 3) / 10}%`,
},
},
},
},
],
},
};
const pictureBuffer = await chartRenderer.renderToBuffer(chart);
writeFileSync(`./a/chart${top}.png`, pictureBuffer);
}
})();
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.