score:0
Accepted answer
here is the solution i was able to find, works for doughnut charts with n datasets.
$('#' + chart_name_donut + '_datalabels').on('change', function () {
var selected = $('#' + chart_name_donut + '_datalabels').val()
if (selected == 'perc') {
isvalue = false;
}
else {
isvalue = true;
}
chart.update();
});
//data recieved from backend
inputarray = <%series_list%>;
mydata = getcolor(inputarray); //assign background color for each part
var mydoughnutextend = chart.controllers.doughnut.prototype.draw;
var ctxdoughnut = document.getelementbyid(chart_name_donut + "_chart").getcontext('2d');
//config options for the doughnut chart,
var config = {
// the type of chart we want to create
type: 'doughnut',
// the data for our dataset
data: mydata,
// configuration options go here
options: {
responsive: true,
maintainaspectratio: false,
legendcallback: function (chart) {
var text = [];
var legsouter = [];
var legsinner = [];
var innerlabel = "";
var outerlabel = "";
//custom legend
for (var j = 0; j < chart.data.datasets.length; j++) {
var legendlabel = chart.data.datasets[j].label;
for (var i = 0; i < chart.data.datasets[j].data.length; i++) {
var newd = { label: chart.data.datasets[j].labels[i], color: chart.data.datasets[j].backgroundcolor[i] };
if (j == 0) {
if (!containsobject(newd, legsouter)) {
legsouter.push(newd);
outerlabel = legendlabel;
outerkeycount = outerkeycount + 1;
}
}
else if (j == 1) {
if (!containsobject(newd, legsinner)) {
legsinner.push(newd);
innerlabel = legendlabel;
innerkeycount = innerkeycount + 1;
}
}
}
}
//change text-align from center to start(left) and end(right)
text.push('<ul class="' + chart.id + '_chart-legend mylegend" style="display:inline-block;position:relative">');
text.push('<li class="labeltitle" style="color:black;display:inline-block;float:left;">' + outerlabel + ': </li>');
for (var k = 0; k < legsouter.length; k++) {
text.push('<li class="labels labels-outer" indexdata="' + k + '" indexdataset="0" ><span style="background-color:' + legsouter[k].color + ';"></span>');
text.push(legsouter[k].label);
text.push('</li>');
}
text.push('<br>')
text.push('<li class="labeltitle" style="color:black;display:inline;float:left;">' + innerlabel + ': </li>');
for (var k = 0; k < legsinner.length; k++) {
text.push('<li class="labels" indexdata="' + k + '" indexdataset="1"><span style="background-color:' + legsinner[k].color + ';"></span>');
text.push(legsinner[k].label);
text.push('</li>');
}
text.push('</ul>');
return text.join("");
},
tooltips: {
position:'cursor',
backgroundcolor: 'rgba(250,250,250,1)',
xpadding: 10,
caretpadding: 5,
caretsize: 0,
cornerradius: 0,
bordercolor: 'rgba(150,150,150,1)',
borderwidth: 1,
bodyfontcolor: 'rgba(0,0,0,1)',
callbacks: { //tooltip callback showing what to display on hover
label: function (tooltipitem, data) {
var dataset = data.datasets[tooltipitem.datasetindex];
var index = tooltipitem.index;
return dataset.labels[index] + ": " + dataset.data[index];
}
}
},
legend: {
display: false
}
}
}
//extension to draw labels on the donut elements, position them, and avoid chart blinking on hover
chart.helpers.extend(chart.controllers.doughnut.prototype,{
draw: function () {
mydoughnutextend.apply(this, arguments);
ctxdoughnut.font = chart.helpers.fontstring(chart.defaults.global.defaultfontfamily, 'normal', chart.defaults.global.defaultfontfamily);
ctxdoughnut.textalign = 'center';
ctxdoughnut.textbaseline = 'bottom';
this.chart.data.datasets.foreach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[object.keys(dataset._meta)[0]].data[i]._model,
total = dataset._meta[object.keys(dataset._meta)[0]].total,
mid_radius = model.innerradius + (model.outerradius - model.innerradius) / 2,
start_angle = model.startangle,
end_angle = model.endangle,
mid_angle = start_angle + (end_angle - start_angle) / 2;
var x = mid_radius * math.cos(mid_angle);
var y = mid_radius * math.sin(mid_angle);
ctxdoughnut.fillstyle = '#fff';
if (i == 3) { // darker text color for lighter background
ctxdoughnut.fillstyle = '#444';
}
var percent = string(math.round(dataset.data[i] / total * 100)) + "%";
//don't display if legend is hide or value is 0 ----
if (dataset.data[i] != 0 && dataset._meta[object.keys(dataset._meta)[0]].data[i].hidden != true) {
if (isvalue == true) {
ctxdoughnut.filltext(dataset.data[i], model.x + x, model.y + y+6);
}
else if (isvalue == false) {
// display percent in another line, line break doesn't work for filltext
ctxdoughnut.filltext(percent, model.x + x, model.y + y+6);
}
}
}
});
}
})
//init chart with config options and type
chart = new chart(ctxdoughnut, config);
//get legend container id
var mylegendcontainer = document.getelementbyid(chart_name_donut + '_legendcontainer');
//draw legend
$(mylegendcontainer).html(chart.generatelegend());
//function to hide/show inner and outer donut parts
function legendclickcallback(event) {
var event = event || window.event;
var target = event.target || event.srcelement;
while (target.nodename !== 'li') {
target = target.parentelement;
}
var parent = target.parentelement;
var chartid = parseint(parent.classlist[0].split("-")[0], 10);
var chart = chart.instances[chartid];
var indexdataset = parseint($(target).attr('indexdataset'));
var indexdata = parseint($(target).attr('indexdata'));
var indexstart = 0;
var indexend = 0;
var meta = chart.getdatasetmeta(indexdataset);
var spanelement = $(target).children();
var colortarget = $(spanelement).css('background-color');
//outer doughnut
if (indexdataset == 0) {
var retainhidden = [];
meta.data[indexdata].hidden = meta.data[indexdata].hidden == false ? !chart.data.datasets[indexdataset].data[indexdata].hidden : false;
indexstart = indexdata * innerkeycount;
indexend = indexstart + innerkeycount;
if (meta.data[indexdata].hidden == true) {
var metainner = chart.getdatasetmeta(indexdataset + 1);
for (var i = indexstart; i < indexend; i++) {
metainner.data[i].hidden = true;
}
}
else if (meta.data[indexdata].hidden == false) {
var numberhidden = $('.donuthiddenelement span').length
var metainner = chart.getdatasetmeta(indexdataset + 1);
if (numberhidden == 0) {
for (var i = indexstart; i < indexend; i++) {
metainner.data[i].hidden = false;
}
}
else {
for (var i = indexstart; i < indexend; i++) {
for (var j = 0; j < numberhidden; j++) {
spanelementcolor = $('.donuthiddenelement span')[j];
if ($(spanelementcolor).css('background-color') == metainner.data[i]._model.backgroundcolor) {
metainner.data[i].hidden = true;
retainhidden.push(metainner.data[i]);
}
else {
if (retainhidden.length == 0) {
metainner.data[i].hidden = false;
}
else {
for (var k = 0; k < retainhidden.length; k++) {
if (metainner.data[i] == retainhidden[k]) {
metainner.data[i].hidden = true;
}
else {
metainner.data[i].hidden = false;
}
}
}
}
}
}
}
}
}
//inner doughnut
else {
//add case here to see which outer element is hidden and which is not
var shownouterelements = [];
var hiddenouterelements = [];
var metaouter = chart.getdatasetmeta(indexdataset - 1);
for (var i = 0; i < metaouter.data.length; i++) {
if (!metaouter.data[i].hidden) {
shownouterelements.push(i);
}
}
for (var i = 0; i < metaouter.data.length; i++) {
if (metaouter.data[i].hidden) {
hiddenouterelements.push(i);
}
}
//if the outer element is shown, change hidden status
if (shownouterelements.length != 0) {
for (var indexouter of shownouterelements) {
initiali = indexouter * (meta.data.length / metaouter.data.length);
endi = initiali + (meta.data.length / metaouter.data.length)
for (var i = initiali; i < endi; i++) {
if (colortarget === meta.data[i]._model.backgroundcolor) {
meta.data[i].hidden = meta.data[i].hidden == false ? !chart.data.datasets[indexdataset].data[i].hidden : false;
if (meta.data[i].hidden == true) {
innerdatavalue[i] = meta.controller._data[i];
metaouter.controller._data[indexouter] = metaouter.controller._data[indexouter] - meta.controller._data[i];
}
else if (meta.data[i].hidden == false) {
metaouter.controller._data[indexouter] = metaouter.controller._data[indexouter] + innerdatavalue[i];
delete innerdatavalue[i];
}
}
}
}
shownouterelements =[]
}
//if the outer element is hidden, keep hidden status but change data anyway
if (hiddenouterelements.length != 0) {
for (var indexouter of hiddenouterelements) {
initiali = indexouter * (meta.data.length / metaouter.data.length);
endi = initiali + (meta.data.length / metaouter.data.length)
for (var i = initiali; i < endi; i++) {
if (colortarget === meta.data[i]._model.backgroundcolor) {
//bug here
if (!$(target).hasclass('donuthiddenelement')) {
innerdatavalue[i] = meta.controller._data[i];
metaouter.controller._data[indexouter] = metaouter.controller._data[indexouter] - meta.controller._data[i];
}
else if ($(target).hasclass('donuthiddenelement')) {
metaouter.controller._data[indexouter] = metaouter.controller._data[indexouter] + innerdatavalue[i];
delete innerdatavalue[i];
}
}
}
}
hiddenouterelements = []
}
$(target).toggleclass('donuthiddenelement');
}
chart.update();
}
//hide outer donut elements by toggling class
$('.labels-outer').click(function () {
$(this).toggleclass('hiddenelementouter')
})
//apply legend callback (on click expand or collapse)
var legenditems = mylegendcontainer.getelementsbyclassname('labels')
for (var i = 0; i < legenditems.length; i += 1) {
legenditems[i].addeventlistener("click", legendclickcallback, false);
}
return chart;
Source: stackoverflow.com
Related Query
- How can I add functionality to Chartjs Doughnut chart custom legend
- How can I add some text in the middle of a half doughnut chart in Chart.JS?
- ChartJS custom legend doughnut separate legend from chart area
- ChartJS - How to add Text between Pie Chart and Legend
- How Can customize chartjs doughnut chart border and tooltip
- Chartjs Custom Legend for Doughnut Chart Having Labelled Lines Sticking Out of Each Section
- How to add text inside the doughnut chart using Chart.js?
- How to modify chartjs tooltip so i can add customized strings in tooltips
- chartjs : how to set custom scale in bar chart
- How to add text in centre of the doughnut chart using Chart.js?
- How to add label for ChartJs Legend
- How to change the color of legend in chartjs and be able to add one more legend?
- Chart.js HTML custom legend issues with doughnut chart
- Chart js: how can I align the legend and the title
- How to create custom legend in ChartJS
- How can I force my ChartJS canvas legend to stay in a single column?
- How to add ChartJS code in Html2Pdf to view image
- How to draw a needle on a custom donut chart and add datapoints to the needle?
- How to add title inside doughnut chart in Angular Chart?
- ChartJS version 3 how to add percentage to pie chart tooltip
- Add Text to Doughnut Chart - ChartJS
- Using chart js version 3, how to add custom data to external tooltip?
- How do I add time sourced from an external source as an X axis to a ChartJS graph?
- how to add percentage value to legend field in pie chart using chart.js
- how to add legend in pie chart
- How can I add a euro sign (€) to all tooltips in my chart js line chart
- How to add text inside the doughnut chart using Chart.js version 3.2.1
- Chartjs - how to change the notation of doughnut chart
- How can I build a double doughnut chart that spins when triggered
- How can I re-distribute values within a charts.js pie chart when a legend item is turned off/on?
More Query from same tag
- ChartJS creating var takes each character and outputs undefined
- TypeError: Cannot read property 'defaults' of undefined when using the react wrapper of chartjs
- Removing legend from chart.js Radar chart
- How to separete chart series into different pane (Chart.js)
- Chart JS - X-Axis base on timezone
- How to display value after the bar using chart.js
- Chat.js, Codeigniter and MySQL. Something wrong on recover data
- angular-chart not showing Pie Chart
- Chartjs annotations-plugin: Can I add multiple vertical lines to identically named x-axis labels?
- How to set ChartJS x-axis title
- Chart.js - mixed chart types (line/bar) on time scale causing offset problems after migration to v3
- How to pass a array from node to .js file (pugJs)
- Chartjs: Bar width
- Can I offset the bars in chart.js stacked bar chart?
- Chart.js canvas resize
- react chart js, title is not displayed
- Need to put border on variablepie highchart?
- ChartJs Uncaught ReferenceError for labels value from ViewBag
- How to offset the legends of the bars in a "chart.js" bar chart?
- Chartjs removing labels and begin number
- Chart.js is only displaying after f12 is pressed
- How to fill a graph by a color till a vertical line using chart.js
- Multiple charts in one page - Chartjs
- daily activity chart using PHP MySQL
- Chart.js data/label scale
- How to set different colors in each stacked bar chart cell?
- chart.js tooltip keeps remembering old data after update
- Return 0 as data for months with no data
- Can't find the chart.js v2 docs
- ChartJs Doughnut parsing datasets