Closed jomarmen closed 5 years ago
@Gabweb Maybe change
for (var val of dataset.data) { total += val; }
to
for (var val of dataset.data) { total += parseFloat(val); }
will be better. To avoid the data in dataset is string type.
@potatopeelings there's a way to change the plugin to accept html instead?
We want to show Doughnut Chart on each post of this wp website Black Friday coupons - but label should be in sidebar of chart.Trying so much.
@potatopeelings replacing afterDraw by beforeDraw avoid tooltip draw problems (hidden by center element)
Hi, I implemented a plugin for showing percentage, value or label in pie or doughnut chart. https://github.com/emn178/Chart.PieceLabel.js It should be helpful.
@dannysindra I applied your code and it worked but is it possible to use other variable names to replace 'ctx'? The whole chart stops working when I replace 'ctx' to another variable name. I can't only use 'ctx' because I need to put more than 6 charts into 1 page.
Hi @tkruu , I am not sure what is the problem. Maybe you could take a look at @Gabweb 's example above? He displayed two charts in 1 page successfully with two different configs.
Any way to get labels outside of the chart? See https://github.com/chartjs/Chart.js/issues/1761
I am also looking for a solution on #1761
Help. I would like to display a percentage label for each segment in half pie/doughnut chart and display in the center the total sum of all segments like:
Take a look at the Code Current : https://jsfiddle.net/AlonsoCauich01/1y9spu7b/
I probably didn't explain myself well. Take a look at the image. I want the total value to change when a label is removed as show in the images, right now the total value stays the same when i remove a value.
@bf2016 You can disable label from chart.js and make label with css as like in this picture. If you want to show label inside donut then use the trailing comments.We have try as it is as you required in backend of our website smarthostingprice. On special requests we can show you how we have do it.
Here is a small script that will do it! http://jsfiddle.net/nkzyx50o/
It will take any amount of text in the doughnut sized perfect for the doughnut. To avoid touching the edges you can set a side-padding as a percentage of the diameter of the inside of the circle. If you don't set it, it will default to 20. You also the color, the font, and the text. The plugin takes care of the rest.
This code is partially based off of the code @potatopeelings provided however does not use a loop to continue resizing the text/redrawing, and only uses the beforeDraw function.
The plugin code will start with a base font size of 30px. From there it will check the width of the text and compare it against the radius of the circle and resize it based off the circle/text width ratio.
This is the plugin code
Chart.pluginService.register({
beforeDraw: function (chart) {
if (chart.config.options.elements.center) {
//Get ctx from string
var ctx = chart.chart.ctx;
//Get options from the center object in options
var centerConfig = chart.config.options.elements.center;
var fontStyle = centerConfig.fontStyle || 'Arial';
var txt = centerConfig.text;
var color = centerConfig.color || '#000';
var sidePadding = centerConfig.sidePadding || 20;
var sidePaddingCalculated = (sidePadding/100) * (chart.innerRadius * 2)
//Start with a base font of 30px
ctx.font = "30px " + fontStyle;
//Get the width of the string and also the width of the element minus 10 to give it 5px side padding
var stringWidth = ctx.measureText(txt).width;
var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
// Find out how much the font can grow in width.
var widthRatio = elementWidth / stringWidth;
var newFontSize = Math.floor(30 * widthRatio);
var elementHeight = (chart.innerRadius * 2);
// Pick a new font size so it will not be larger than the height of label.
var fontSizeToUse = Math.min(newFontSize, elementHeight);
//Set font settings to draw it correctly.
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.font = fontSizeToUse+"px " + fontStyle;
ctx.fillStyle = color;
//Draw text in center
ctx.fillText(txt, centerX, centerY);
}
}
});
And you will use the following options in your chart object.
options: {
elements: {
center: {
text: 'Desktop',
color: '#36A2EB', //Default black
fontStyle: 'Helvetica', //Default Arial
sidePadding: 15 //Default 20 (as a percentage)
}
}
}
@ShawnCorrigan this is exactly the fix needed to solve the original issue (from 2013) that @jomarmen was asking about.
Thank you for breaking out the plugin from the options in your comment, that was very helpful in understanding how to implement it. This worked perfectly for me, very much appreciated!
How to implement something like this?
I edited the plugin but it's not absolutely correct: Chart.pluginService.register({ afterDraw(chart) { if (chart.center) { const centerConfig = chart.config.options.elements.center; const ctx = chart.chart.ctx; ctx.save(); ctx.font = chart.center.font; ctx.fillStyle = chart.center.fillStyle; ctx.textAlign = 'center'; ctx.textBaseline = 'top'; const centerX = (chart.chartArea.left + chart.chartArea.right); const centerY = (chart.chartArea.top + chart.chartArea.bottom); ctx.fillText(centerConfig.text, centerX, centerY); ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; const centerXnumb = (chart.chartArea.left + chart.chartArea.right) / 2; const centerYnumb = (chart.chartArea.top + chart.chartArea.bottom) / 2.4; ctx.fillText(centerConfig.textNumber, centerXnumb, centerYnumb); ctx.restore(); } } });
It is displayed something like this:
The options is:
elements: {
center: {
textNumber: ${sectorsCounter}
,
text: intl.formatMessage({ id: 'pie.sectors' }),
fontColor: '#656566',
fontFamily: 'EurobankSans',
fontStyle: 'normal',
minFontSize: 25,
maxFontSize: 25,
}
},
I added the center label easily with an absolute positioned HTML element, though having this feature natively to ChartJS would be cool. What brought me here and what I'm really pining for is something like @dannysindra 's example of having percentage labels (or even just having the tooltips always on) inside each area of the chart. I've tried implementing it in our Angular app but am having trouble. A built in solution to do this seems like a no-brainer. Add my voice to that feature request!
@emn178 just tried your solution and its working! you are awesome!
to get this working I extended the draw function for Chart,Tooltip with the following:
if (this._chart.options.tooltips.displayPercentage) {
var activeChart = this._chart;
var cx = activeChart.width / 2;
var cy = activeChart.chartArea.top + ((activeChart.height - activeChart.chartArea.top) / 2);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = '28px Arial';
ctx.fillStyle = "#63666A";
var total = _.sum(activeChart.data.datasets[0].data);
var percent = 100 * activeChart.data.datasets[0].data[vm.dataPoints[0].index] / total;
ctx.fillText(Math.round(percent) + "%", cx, cy);
}
You can now add on the options for tooltip whether to display percentage or not, and it'll appear in the center when hovering. The sum calculation is using lodash, this could be a simple function
Hi, I've tried all the possibilities to make tooltip visible always. But nothing works. Kindly help to fix this, The data is passed as a string which is fetched from database.
var ctx2 = document.getElementById("PieChart2"); var options = { title: { display: true, maintainAspectRatio: true, responsive: false, text: 'Predicted risks from Data' }, events: [], 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);
}
}
};
var scatterChart = new Chart(ctx2, {
type: 'pie',
data: {
labels: [${piePlot2.age}],
datasets: [{
backgroundColor: [
"#ff6969",
"#ffb4b4",
"red",
"#ff2d2d"
],
data: [<c:out value='${piePlot2.result}'/>]
}]
}
});
When hovering, it is displays the data. But i want it be appeared always. Any help!
Thanks in Advance!
+1
Any news on whether this is being still being worked on or planned for a release as I noticed it has been added and removed to milestones multiples times.
@ShawnCorrigan that is excellent as it's responsive
.
Edit: actually found an issue with this. Destroy / re adding the chart - the text keeps on adding on and get's blurry.
Any of this solutions is working on my code, can someone help me?
Here is the HTML code: `
</div>`
and javascript code:
var confi2 = { type: 'doughnut', data: { datasets: [{ data: [ "33.33333", "33.33333", "33.33333", ], backgroundColor: [ "#FFFFFF", "#009688", "#FFFFFF", ], }, { data: [ "64", "36", ], backgroundColor: [ "#F41616", "#FFFFFF", ], },{ data: [ "111", ], backgroundColor: [ "#948F8F", ], }] }, options: { responsive: true, } };
var ctx = document.getElementById("chart-area").getContext("2d"); window.myDoughnut = new Chart(ctx, confi2);
Thank you on advise
//Plugin for center text
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 160).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "top";
var text = "Foo-bar",
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
So what it actually does is, it takes the height, width of the chart and then places the desired text at half the height and width of your chart. You don't have to worry about the responsiveness and changing size(handled similarly) of the chart. Its completely dynamic this way.
I have almost no experience with JavaScript, and I need to put a FontAwesome icon inside the doughnut chart. It would be a chart to show the temperature, and the thermometer icon should be in it's middle. Could anyone help me?
@gabarreto Here is not the best place to ask questions about implementation. I recommend creating a question in StackOveflow with the tag chart.js.
To expand on the plugin provided by @abhinav1602 to center text, I did the following to show percentage on my doughnut charts:
// Just copy and paste this bit above your chart inits. It will only apply to doughnuts.
Chart.pluginService.register({
beforeDraw: function(chart) {
if(chart.chart.chart.config.type=='doughnut'){
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 160).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "top";
// Ensure your first data is the percentage data in your dataset
var chart_percent = chart.chart.chart.data.datasets[0].data[0];
chart_percent = chart_percent || 0;
var text = chart_percent+'%',
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
}
});
An example of my usage:
this.doughnutChart1 = new Chart(this.doughnutCanvas1.nativeElement, {
type: 'doughnut',
data: {
datasets: [{
// So this donut is 75% as per the first data item (will reflect with the txt plugin)
data: [75,25],
borderWidth: 0,
backgroundColor: [
'#67bebf',
'#caced5',
],
hoverBackgroundColor: [
"#67bebf",
"#caced5",
]
}]
},
options: {
cutoutPercentage: 90
}
});
I've added a new plugin that allows to display multiple lines of text in the center of the doughnut on Github: chartjs-plugin-doughnutlabel if that helps. See the Demo.
To place the text in the center, you need to consider the size of the font size. another fix for the solution of gbrits. in the textY `object:
textY = (height / 2) - (fontSize * 16 / 2)
I'm going to close this issue since many solutions exist now and maintainers decided to not add it to the core package. I think the best approach is to use a plugin such as chartjs-plugin-doughnutlabel (thanks @ciprianciurea) and at some point, the datalabels plugin may also offer a (limited) way to center labels.
@ciprianciurea feel free to open a PR adding it to the docs.
Below the code work for me, but in the centre text (100%) appearing in another chart in same page !.
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 160).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "top";
var text = "100%",
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
Does anyone have an updated plugin for center doughnut labels for chartJS v4?
Does anyone have an updated plugin for center doughnut labels for chartJS v4?
AFAIK there isn't. There is a pending PR in chartjs-plugin-annotation for that: https://github.com/chartjs/chartjs-plugin-annotation/pull/825
Can you please reopen this issue? Seems like no one cares about the plugin.
Hi,
I would like to be able to add a label inside a donut chart like this charts
Thks