chartjs-plugin-datalabels
chartjs-plugin-datalabels copied to clipboard
Arc labels around "pie" or "doughnut" charts
Thank you for the last release enabling multiple labels. It works nicely. Nevertheless, it would be great to be able to arc labels positionned outside "pie" or "doughnut" charts. This option (arc: boolean) exists on a similar library: https://emn178.github.io/chartjs-plugin-labels/samples/demo/
This is the "renderArcLabel" function (see line 141 of js file) that allows labels to arc.
Do you think such a function could be easily added to this plugin? I would be happy to help more but i'm afraid i'm not skilled enough for that.
Thanks for this nice plugin! I would also appreciate this functionality
+1. Looking for label arcing as well. Would be nice to have the option to arc either within the chart or outside the chart.
Is this future going to be added one day? Someone found a solution to this?
Similar to #93
On Chart.js v4.4 with plugin chartjs/chartjs-plugin-datalabels v2.2
On Chart.js v2.9 with plugin emn178/chartjs-plugin-labels v1.1
I solved this issue by adding a variable checking if we should fix is upside down
- for (let i = 0; i < line.length; i++) {
- const char = line.charAt(i);
- mertrics = ctx.measureText(char);
- ctx.save();
- ctx.translate(0, -1 * radius);
- ctx.fillText(char, 0, y);
- ctx.restore();
- ctx.rotate(mertrics.width / radius);
- }
+ for (let i = 0; i < reversedLine.length; i++) {
+ const char = reversedLine.charAt(i);
+ const metrics = ctx.measureText(char);
+ const charWidth = metrics.width;
+
+ ctx.save();
+ // Translate to the correct radius and rotate the canvas to the start angle
+ ctx.translate(0, -1 * radius);
+ ctx.save();
+ ctx.translate(charWidth / 8, 0);
+ ctx.rotate(Math.PI); // This rotation flips the character
+
+ // The y position is adjusted by the offset and the height of the characters
+ ctx.fillText(char, 0, y);
+
+ // Rotate the context back for the next character
+ ctx.restore();
+ ctx.restore();
+ // Adjust the rotation for each character
+ ctx.rotate(charWidth / radius);
+ }
Here's the whole code
if (shouldReverseArc) {
ctx.rotate(renderInfo.startAngle);
ctx.textBaseline = "middle";
ctx.textAlign = "right";
const lines = label.split("\n");
let max = 0;
const widths = [];
let offset = 0;
if (this.options.position === "border") {
offset = ((lines.length - 1) * this.getFontSize(label)) / 2;
}
let mertrics;
for (let j = 0; j < lines.length; ++j) {
mertrics = ctx.measureText(lines[j]);
if (mertrics.width > max) {
max = mertrics.width;
}
widths.push(mertrics.width);
}
for (let j = 0; j < lines.length; ++j) {
const line = lines[j];
// Reverse the characters in the line to draw in reverse
const reversedLine = line.split("").reverse().join("");
const y =
(lines.length - 1 - j) *
(this.getFontSize(label) + this.getFontSize(label) * 0.8) +
offset;
const padding = (max - widths[j]) / 2;
ctx.rotate(padding / radius);
for (let i = 0; i < reversedLine.length; i++) {
const char = reversedLine.charAt(i);
const metrics = ctx.measureText(char);
const charWidth = metrics.width;
ctx.save();
// Translate to the correct radius and rotate the canvas to the start angle
ctx.translate(0, -1 * radius);
ctx.save();
ctx.translate(charWidth / 8, 0);
ctx.rotate(Math.PI); // This rotation flips the character
// The y position is adjusted by the offset and the height of the characters
ctx.fillText(char, 0, y);
// Rotate the context back for the next character
ctx.restore();
ctx.restore();
// Adjust the rotation for each character
ctx.rotate(charWidth / radius);
}
}
}
This helped me with fixing the issue. Change depending usage I guess.