I am working on stacked Bar charts using chart.js.
I need to show labels in middle of Bars as percentage and total sum on top of bars stacked together. Currently, I am able to show their percentage after searching for code. But that percentages are not correct mathematically. I have added that code in js fiddle. Hope I got some help for it. I am just weak in js.
https://jsfiddle.net/n4nish/hca3wdgq/4/
HTML -
var data = [{
label: 'New',
backgroundColor: '#1d3f74',
data: [6310, 5742, 4044, 5564]
}, {
label: 'Repeat',
backgroundColor: '#6c92c8',
data: [11542, 12400, 12510, 11450]
}];
var options = {
maintainAspectRatio: false,
spanGaps: false,
responsive: true,
legend: {
display: true,
position: 'bottom',
labels: {
fontColor: "#fff",
boxWidth: 14,
fontFamily: 'proximanova'
}
},
tooltips: {
mode: 'label',
callbacks: {
label: function (tooltipItem, data) {
var type = data.datasets[tooltipItem.datasetIndex].label;
var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var total = 0;
for (var i = 0; i < data.datasets.length; i++)
total += data.datasets[i].data[tooltipItem.index];
if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
return type + " : " + value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, '1,');
} else {
return [type + " : " + value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, '1,'), "Overall : " + total];
}
}
}
},
plugins: {
datalabels: {
formatter: function (value, ctx) {
let sum = 0;
let dataArr = ctx.chart.data.datasets[0].data;
dataArr.map(data => {
sum += data;
});
let percentage = (value * 100 / sum).toFixed(0) + "%";
return percentage;
},
font: {
weight: "normal"
},
color: "#fff"
}
},
scales: {
xAxes: [{
stacked: true,
gridLines: {
display: false
},
ticks: {
fontColor: "#fff"
}
}],
yAxes: [{
stacked: true,
display: false,
ticks: {
fontColor: "#fff"
}
}]
}
};
var ctx = document.getElementById("mychart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Jun", "July", "Aug", "Sept"],
datasets: data
},
options: options
});
You can set options that will apply to:
all labels in the chart:
options.plugins.datalabels.*
only a single dataset:
dataset.datalabels.*
// Label formatter function
const formatter = (value, ctx) => {
const otherDatasetIndex = ctx.datasetIndex === 0 ? 1 : 0;
const total =
ctx.chart.data.datasets[otherDatasetIndex].data[ctx.dataIndex] + value;
return `${(value / total * 100).toFixed(0)}%`;
};
const data = [{
// stack: 'test',
label: "New",
backgroundColor: "#1d3f74",
data: [6310, 5742, 4044, 5564],
// Change options only for labels of THIS DATASET
datalabels: {
color: "white",
formatter: formatter
}
},
{
// stack: 'test',
label: "Repeat",
backgroundColor: "#6c92c8",
data: [11542, 12400, 12510, 11450],
// Change options only for labels of THIS DATASET
datalabels: {
color: "yellow",
formatter: formatter
}
}
];
const options = {
maintainAspectRatio: false,
spanGaps: false,
responsive: true,
legend: {
display: true,
position: "bottom",
labels: {
fontColor: "#fff",
boxWidth: 14,
fontFamily: "proximanova"
}
},
tooltips: {
mode: "label",
callbacks: {
label: function(tooltipItem, data) {
const type = data.datasets[tooltipItem.datasetIndex].label;
const value =
data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
let total = 0;
for (let i = 0; i < data.datasets.length; i++)
total += data.datasets[i].data[tooltipItem.index];
if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
return (
type + " : " + value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "1,")
);
} else {
return [
type +
" : " +
value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "1,"),
"Overall : " + total
];
}
}
}
},
plugins: {
// Change options for ALL labels of THIS CHART
datalabels: {
color: "#white",
align: "center"
}
},
scales: {
xAxes: [{
stacked: true,
gridLines: {
display: false
},
ticks: {
fontColor: "#fff"
}
},
{
type: 'category',
offset: true,
position: 'top',
ticks: {
fontColor: "#fff",
callback: function(value, index, values) {
return data[0].data[index] + data[1].data[index]
}
}
}
],
yAxes: [{
stacked: true,
display: false,
ticks: {
fontColor: "#fff"
}
}]
}
};
const ctx = document.getElementById("mychart").getContext("2d");
new Chart(ctx, {
type: "bar",
data: {
labels: ["Jun", "July", "Aug", "Sept"],
datasets: data
},
options: options
});
body {
background: #20262e;
font-family: Helvetica;
padding-top: 50px;
}
#mychart {
height: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-datalabels.min.js"></script>
<canvas id="mychart"></canvas>
Codepen
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With