is there any way to do a stacked and grouped bar chart with Chart.js library?
It should look something like this http://www.highcharts.com/demo/column-stacked-and-grouped
The stacked bar chart (aka stacked bar graph) extends the standard bar chart from looking at numeric values across one categorical variable to two. Each bar in a standard bar chart is divided into a number of sub-bars stacked end to end, each one corresponding to a level of the second categorical variable.
A grouped bar chart (aka clustered bar chart, multi-series bar chart) extends the bar chart, plotting numeric values for levels of two categorical variables instead of one. Bars are grouped by position for levels of one categorical variable, with color indicating the secondary category level within each group.
Dot plot. An alternative to the bar or column panel charts is a dot plot. The advantage is that all points are plotted in the same XY space, allowing for easier comparisons.
OK, I found the solution. It's described in this GitHub issue and solution is in this JSFiddle
Chart.defaults.groupableBar = Chart.helpers.clone(Chart.defaults.bar);
var helpers = Chart.helpers;
Chart.controllers.groupableBar = Chart.controllers.bar.extend({
calculateBarX: function (index, datasetIndex) {
// position the bars based on the stack index
var stackIndex = this.getMeta().stackIndex;
return Chart.controllers.bar.prototype.calculateBarX.apply(this, [index, stackIndex]);
},
hideOtherStacks: function (datasetIndex) {
var meta = this.getMeta();
var stackIndex = meta.stackIndex;
this.hiddens = [];
for (var i = 0; i < datasetIndex; i++) {
var dsMeta = this.chart.getDatasetMeta(i);
if (dsMeta.stackIndex !== stackIndex) {
this.hiddens.push(dsMeta.hidden);
dsMeta.hidden = true;
}
}
},
unhideOtherStacks: function (datasetIndex) {
var meta = this.getMeta();
var stackIndex = meta.stackIndex;
for (var i = 0; i < datasetIndex; i++) {
var dsMeta = this.chart.getDatasetMeta(i);
if (dsMeta.stackIndex !== stackIndex) {
dsMeta.hidden = this.hiddens.unshift();
}
}
},
calculateBarY: function (index, datasetIndex) {
this.hideOtherStacks(datasetIndex);
var barY = Chart.controllers.bar.prototype.calculateBarY.apply(this, [index, datasetIndex]);
this.unhideOtherStacks(datasetIndex);
return barY;
},
calculateBarBase: function (datasetIndex, index) {
this.hideOtherStacks(datasetIndex);
var barBase = Chart.controllers.bar.prototype.calculateBarBase.apply(this, [datasetIndex, index]);
this.unhideOtherStacks(datasetIndex);
return barBase;
},
getBarCount: function () {
var stacks = [];
// put the stack index in the dataset meta
Chart.helpers.each(this.chart.data.datasets, function (dataset, datasetIndex) {
var meta = this.chart.getDatasetMeta(datasetIndex);
if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {
var stackIndex = stacks.indexOf(dataset.stack);
if (stackIndex === -1) {
stackIndex = stacks.length;
stacks.push(dataset.stack);
}
meta.stackIndex = stackIndex;
}
}, this);
this.getMeta().stacks = stacks;
return stacks.length;
},
});
var data = {
labels: ["January", "February", "March"],
datasets: [
{
label: "Apples",
backgroundColor: "rgba(99,255,132,0.2)",
data: [20, 10, 30],
stack: 1
},
{
label: "Bananas",
backgroundColor: "rgba(99,132,255,0.2)",
data: [40, 50, 20],
stack: 1
},
{
label: "Cookies",
backgroundColor: "rgba(255,99,132,0.2)",
data: [60, 20, 20],
stack: 1
},
{
label: "Apples",
backgroundColor: "rgba(99,255,132,0.2)",
data: [20, 10, 30],
stack: 2
},
{
label: "Bananas",
backgroundColor: "rgba(99,132,255,0.2)",
data: [40, 50, 20],
stack: 2
},
{
label: "Cookies",
backgroundColor: "rgba(255,99,132,0.2)",
data: [60, 20, 20],
stack: 2
},
{
label: "Apples",
backgroundColor: "rgba(99,255,132,0.2)",
data: [20, 10, 30],
stack: 3
},
{
label: "Bananas",
backgroundColor: "rgba(99,132,255,0.2)",
data: [40, 50, 20],
stack: 3
},
{
label: "Cookies",
backgroundColor: "rgba(255,99,132,0.2)",
data: [60, 20, 20],
stack: 3
},
]
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, {
type: 'groupableBar',
data: data,
options: {
legend: {
labels: {
generateLabels: function(chart) {
return Chart.defaults.global.legend.labels.generateLabels.apply(this, [chart]).filter(function(item, i){
return i <= 2;
});
}
}
},
scales: {
yAxes: [{
ticks: {
max: 160,
},
stacked: true,
}]
}
}
});
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