Closed jomarmen closed 6 years ago
me too +1
+1
+1
+1
+1
Would putting this data in an HTML absolutely positioned element over the top of the doughnut not be a better solution than adding more to chart.js to achieve this?
+1
It's fairly easy to do this with HTML, but it would be nice if the chart exposed some sort of event API to hook into to populate the value.
+1
+1
+1
Although, as well as a label I think it would also be good to have it auto add the sum-total of the data put in, or the data type etc
I may work on a way to pass this in if I get the chance this week, though doing the total automatically shouldn't be too much of a stretch.
+1
is there any option to write label for each section?
+1
Yes, this can be accomplished easily with HTML, but I would love to see something like this implemented into the core.
+1
+1
+2
+3
-1 I think the HTML approach is better. The label will only make sense inside the canvas if it is very small.
I would consider these to be a special-purpose of pie chart: single value pie charts with label in the middle.
Recommending implementation should be outside chart.js
@fulldecent The advantage to having a label/legend built into the chart is that the user can take the image itself and use it in another doc or presentation without having to re-create the legend. In fact, for my users, this is an absolute requirement - a chart without a legend is useless to them. Whether that should be within the scope of chart.js is debatable, but I would guess there are many devs that would agree with me on this one. I could be wrong though.
+1
+1
tagging: NEW CHART TYPES
This may be useful for some of you since I've had the same requirement a few weeks ago. https://github.com/fixanoid/Pretty-Doughtnut
Any solution about it (http://stackoverflow.com/questions/20911919/put-sum-of-values-in-center-of-doughnut-chart) ?
+1
I don't think having a label in the middle of the chart is quite yet needed in the core logic of chartjs. We will probably soon be adding new event-hook-like api's into the core though, that would allow you to achieve this quite easily in a custom implementation along with a lot of other things.
the main problem I can see with your design is the top left slice (0%), evaluating those exception is probably one of the reason why your design is not implemented.
yes, I got it. What do you do when the slice is small?
+1
+1
+1
As joetime mentioned above, this feature will be pretty useful for clients. Currently mine are making the charts manually from an Excel file, then copy-paste the pie charts into their PPT files.
Please consider adding this feature, as I saw it there are so many requests since 2013 for this 👍
Also, I would love to know how to make the pie slices show percentage instead of raw number. Anyone has found a way to achieve these things temporarily? Any help will be much appreciated!
+1
Still no update on whether this request will be implemented? For anyone interested on pie chart, I found a workaround by forcing the tooltip to always appear (from this answer on SO):
Here is the config, you will need to modify the animation property:
var options = {
...
events: false,
animation: {
duration: 0,
onComplete: function () {
var self = this;
var elementsArray = [];
Chart.helpers.each(self.data.datasets, function (dataset, datasetIndex) {
Chart.helpers.each(dataset.metaData, function (element, index) {
var tooltip = new Chart.Tooltip({
_chart: self.chart,
_chartInstance: self,
_data: self.data,
_options: self.options,
_active: [element]
}, self);
tooltip.update();
tooltip.transition(Chart.helpers.easingEffects.linear).draw();
}, self);
}, self);
}
},
...
}
As you can see, the tooltips are overlapping each other, and some tooltips still appears if the segments contain zero data. Anyone knows how to fix this? I also want to change the balloons to appear above, instead of from left or right. The pie chart below is a good example:
Any help will be appreciated!
+1
Hi guys, starting from chart.js v2.1, I was able to get the pie chart to show labels in percentages. Here is my code - hopefully it will work for everyone. Put this inside your chart options:
...,
animation: {
duration: 0,
onComplete: function () {
var self = this,
chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = '18px Arial';
ctx.textAlign = "center";
ctx.fillStyle = "#ffffff";
Chart.helpers.each(self.data.datasets.forEach((dataset, datasetIndex) => {
var meta = self.getDatasetMeta(datasetIndex),
total = 0, //total values to compute fraction
labelxy = [],
offset = Math.PI / 2, //start sector from top
radius,
centerx,
centery,
lastend = 0; //prev arc's end line: starting with 0
for (var val of dataset.data) { total += val; }
Chart.helpers.each(meta.data.forEach((element, index) => {
radius = 0.9 * element._model.outerRadius - element._model.innerRadius;
centerx = element._model.x;
centery = element._model.y;
var thispart = dataset.data[index],
arcsector = Math.PI * (2 * thispart / total);
if (element.hasValue() && dataset.data[index] > 0) {
labelxy.push(lastend + arcsector / 2 + Math.PI + offset);
}
else {
labelxy.push(-1);
}
lastend += arcsector;
}), self)
var lradius = radius * 3 / 4;
for (var idx in labelxy) {
if (labelxy[idx] === -1) continue;
var langle = labelxy[idx],
dx = centerx + lradius * Math.cos(langle),
dy = centery + lradius * Math.sin(langle),
val = Math.round(dataset.data[idx] / total * 100);
ctx.fillText(val + '%', dx, dy);
}
}), self);
}
},
...
Cheers
Anyone any tips on achieving a label inside of a donut chart? (as per the original issue) It would be great to find out how to do this in 2.x...
Thanks in advance!
Yes please add functionality for this..
Tried with the html element solution but that won't work if you want it to be responsive.. Also can't always calculate the position from the canvas as the amount of labels might mess upp the position of the donut itself
Here's one way to do it using the newly added plugin service - http://jsfiddle.net/s9tu1c9y/
Yaay plugins!
If you don't need the plugin to figure out the font size, you can probably take out a bit of code - this bit of code treats the text as a line while trying to fit it in the inner diameter. If you want to be really accurate, you should actually treat it as a rectangle but I figure its not worth the complexity - if the corners of your text overlap with the chart sectors, just add some spaces before and after your maxText
The plugin code
Chart.pluginService.register({
afterUpdate: function (chart) {
if (chart.config.options.elements.center) {
var helpers = Chart.helpers;
var centerConfig = chart.config.options.elements.center;
var globalConfig = Chart.defaults.global;
var ctx = chart.chart.ctx;
var fontStyle = helpers.getValueOrDefault(centerConfig.fontStyle, globalConfig.defaultFontStyle);
var fontFamily = helpers.getValueOrDefault(centerConfig.fontFamily, globalConfig.defaultFontFamily);
if (centerConfig.fontSize)
var fontSize = centerConfig.fontSize;
// figure out the best font size, if one is not specified
else {
ctx.save();
var fontSize = helpers.getValueOrDefault(centerConfig.minFontSize, 1);
var maxFontSize = helpers.getValueOrDefault(centerConfig.maxFontSize, 256);
var maxText = helpers.getValueOrDefault(centerConfig.maxText, centerConfig.text);
do {
ctx.font = helpers.fontString(fontSize, fontStyle, fontFamily);
var textWidth = ctx.measureText(maxText).width;
// check if it fits, is within configured limits and that we are not simply toggling back and forth
if (textWidth < chart.innerRadius * 2 && fontSize < maxFontSize)
fontSize += 1;
else {
// reverse last step
fontSize -= 1;
break;
}
} while (true)
ctx.restore();
}
// save properties
chart.center = {
font: helpers.fontString(fontSize, fontStyle, fontFamily),
fillStyle: helpers.getValueOrDefault(centerConfig.fontColor, globalConfig.defaultFontColor)
};
}
},
afterDraw: function (chart) {
if (chart.center) {
var centerConfig = chart.config.options.elements.center;
var ctx = chart.chart.ctx;
ctx.save();
ctx.font = chart.center.font;
ctx.fillStyle = chart.center.fillStyle;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var centerX = (chart.chartArea.left + chart.chartArea.right) / 2;
var centerY = (chart.chartArea.top + chart.chartArea.bottom) / 2;
ctx.fillText(centerConfig.text, centerX, centerY);
ctx.restore();
}
},
})
and then
...
options: {
elements: {
center: {
// the longest text that could appear in the center
maxText: '100%',
text: '90%',
fontColor: '#36A2EB',
fontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
fontStyle: 'normal',
// fontSize: 12,
// if a fontSize is NOT specified, we will scale (within the below limits) maxText to take up the maximum space in the center
// if these are not specified either, we default to 1 and 256
minFontSize: 1,
maxFontSize: 256,
}
}
}
};
@dannysindra thank you very much for your example, it works very well, but the percentages flicker every time I mouse over the pie chart, is there any way to avoid this?
@MoPHL I have not solved that part completely, but there is a way to prevent flicker on "mouseover" event (still flicker on "mouseclick").
To do it simply empty the events list array:
...,
events: [""],
animation: {
...
}
Empty array will not do, so I supplied empty string inside the array to make it work. Note that the tooltip will also not appear on mouseover.
@dannysindra I have also tried disabling the events, but I still need to retain the tooltips, etc.
By combining both solutions from @potatopeelings and @dannysindra I manged to get it work. It won't flicker and after some changes to those forEach() it now works on iOS too.
I Implemented two options to either show the labels or percentages. Take a look at the Code: http://jsfiddle.net/Gabweb/s15jj21a/
In my case I had to implement it differently in order to achieve animated percentages - (even when you hide and show segments). Still needs some work.
It would be nice if we had this implemented in the core :) .. Although I'm seeing comments that it's better to implement it in other ways, so I might be wrong.
@jorgecgll very nice, it's working very well and found no issues so far.
I'm using the plugin above and it works like a charm. I'm currently updating the chart value every 5s and I was wondering if there is a way to trigger the redraw of the element text.
thanks
👍
👍
Whats the status on this issue?
The status is: waiting for pull request. Please use the notification feature on the right side of the screen here to be automatically notified for further status updates.
Hi,
I would like to be able to add a label inside a donut chart like this charts
Thks