Reputation: 11
<!DOCTYPE html>
<html>
<head>
<title>Task Status Bar Chart</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="myChart"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['ToDo', 'InProgress', 'Done'],
datasets: [
{
label: 'Under Review',
data: [
[10, 5, 0], // Blocker
[20, 10, 5], // High
[5, 10, 20], // Low
[5, 5, 10], // Critical
[10, 15, 15] // Medium
],
backgroundColor: [
'rgba(255, 99, 132, 0.5)',
'rgba(54, 162, 235, 0.5)',
'rgba(255, 206, 86, 0.5)',
'rgba(75, 192, 192, 0.5)',
'rgba(153, 102, 255, 0.5)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
},
{
label: 'In Progress',
data: [
[10, 5, 0], // Blocker
[20, 10, 5], // High
[5, 10, 20], // Low
[5, 5, 10], // Critical
[10, 15, 15] // Medium
],
backgroundColor: [
'rgba(255, 99, 132, 0.5)',
'rgba(54, 162, 235, 0.5)',
'rgba(255, 206, 86, 0.5)',
'rgba(75, 192, 192, 0.5)',
'rgba(153, 102, 255, 0.5)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
},
{
label: 'New',
data: [
[10, 5, 0], // Blocker
[20, 10, 5], // High
[5, 10, 20], // Low
[5, 5, 10], // Critical
[10, 15, 15] // Medium
],
backgroundColor: [
'rgba(255, 99, 132, 0.5)',
'rgba(54, 162, 235, 0.5)',
'rgba(255, 206, 86, 0.5)',
'rgba(75, 192, 192, 0.5)',
'rgba(153, 102, 255, 0.5)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
},
{
label: 'Completed',
data: [
[10, 5, 0], // Blocker
[20, 10, 5], // High
[5, 10, 20], // Low
[5, 5, 10], // Critical
[10, 15, 15] // Medium
],
backgroundColor: [
'rgba(255, 99, 132, 0.5)',
'rgba(54, 162, 235, 0.5)',
'rgba(255, 206, 86, 0.5)',
'rgba(75, 192, 192, 0.5)',
'rgba(153, 102, 255, 0.5)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
}
]
},
options: {
indexAxis: 'y',
scales: {
x: {
stacked: false
},
y: {
stacked: false
}
}
}
});
</script>
</body>
</html>
The result showed up like this: Output I was expecting something like this: Expectation I was expecting a Stacked Grouped Chart: For example:
X-axis: ToDo, InProgress, Done
Each x-axis label has 4 stacks: [Under Review, In Progress, New, Completed] 3 - 4
Now each stack has 5 data points: [Blocked, High, Critical, Low, Medium] 4 - 5
Upvotes: 0
Views: 44
Reputation: 647
You could use a Stacked Bar Chart with Groups, which allows you to have a stacked bar graph with control over how the data is grouped.
With this approach, you will need to have distinct data entries for each data point in each stack. This means that you will need to define "Blocked" data for the Under Review, In Progress, New and Completed stacks.
You will also need to use a plugin called chartjs-plugin-datalabels, which allows you to label the different groups/stacks.
Two known issues with the included code:
The code is as follows:
// Register the plugin (chartjs-plugin-datalabels).
// Needed for the stack labels to work.
Chart.register(ChartDataLabels);
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['ToDo', 'InProgress', 'Done'],
datasets: [{
label: 'Blocker',
data: [10, 5, 0],
borderWidth: 1,
backgroundColor: 'rgba(255, 99, 132, 0.5)',
borderColor: 'rgba(255, 99, 132, 1)',
stack: 'Under Review',
},
{
label: 'High',
data: [20, 10, 5],
borderWidth: 1,
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
stack: 'Under Review',
},
{
label: 'Low',
data: [5, 10, 20],
borderWidth: 1,
backgroundColor: 'rgba(75, 192, 192, 0.5)',
borderColor: 'rgba(75, 192, 192, 1)',
stack: 'Under Review',
},
{
label: 'Critical',
data: [5, 5, 10],
borderWidth: 1,
backgroundColor: 'rgba(255, 206, 86, 0.5)',
borderColor: 'rgba(255, 206, 86, 1)',
stack: 'Under Review',
},
{
label: 'Medium',
data: [10, 15, 15],
borderWidth: 1,
backgroundColor: 'rgba(153, 102, 255, 0.5)',
borderColor: 'rgba(153, 102, 255, 1)',
stack: 'Under Review',
},
{
label: 'Blocker',
data: [0, 25, 10],
borderWidth: 1,
backgroundColor: 'rgba(255, 99, 132, 0.5)',
borderColor: 'rgba(255, 99, 132, 1)',
stack: 'In Progress',
},
{
label: 'High',
data: [2, 8, 6],
borderWidth: 1,
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
stack: 'In Progress',
},
{
label: 'Low',
data: [15, 0, 9],
borderWidth: 1,
backgroundColor: 'rgba(75, 192, 192, 0.5)',
borderColor: 'rgba(75, 192, 192, 1)',
stack: 'In Progress',
},
{
label: 'Critical',
data: [12, 6, 18],
borderWidth: 1,
backgroundColor: 'rgba(255, 206, 86, 0.5)',
borderColor: 'rgba(255, 206, 86, 1)',
stack: 'In Progress',
},
{
label: 'Medium',
data: [3, 4, 7],
borderWidth: 1,
backgroundColor: 'rgba(153, 102, 255, 0.5)',
borderColor: 'rgba(153, 102, 255, 1)',
stack: 'In Progress',
},
{
label: 'Blocker',
data: [10, 5, 0],
borderWidth: 1,
backgroundColor: 'rgba(255, 99, 132, 0.5)',
borderColor: 'rgba(255, 99, 132, 1)',
stack: 'New',
},
{
label: 'High',
data: [20, 10, 5],
borderWidth: 1,
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
stack: 'New',
},
{
label: 'Low',
data: [5, 10, 20],
borderWidth: 1,
backgroundColor: 'rgba(75, 192, 192, 0.5)',
borderColor: 'rgba(75, 192, 192, 1)',
stack: 'New',
},
{
label: 'Critical',
data: [5, 5, 10],
borderWidth: 1,
backgroundColor: 'rgba(255, 206, 86, 0.5)',
borderColor: 'rgba(255, 206, 86, 1)',
stack: 'New',
},
{
label: 'Medium',
data: [10, 15, 15],
borderWidth: 1,
backgroundColor: 'rgba(153, 102, 255, 0.5)',
borderColor: 'rgba(153, 102, 255, 1)',
stack: 'New',
},
{
label: 'Blocker',
data: [0, 25, 10],
borderWidth: 1,
backgroundColor: 'rgba(255, 99, 132, 0.5)',
borderColor: 'rgba(255, 99, 132, 1)',
stack: 'Completed',
},
{
label: 'High',
data: [2, 8, 6],
borderWidth: 1,
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
stack: 'Completed',
},
{
label: 'Low',
data: [15, 0, 9],
borderWidth: 1,
backgroundColor: 'rgba(75, 192, 192, 0.5)',
borderColor: 'rgba(75, 192, 192, 1)',
stack: 'Completed',
},
{
label: 'Critical',
data: [12, 6, 18],
borderWidth: 1,
backgroundColor: 'rgba(255, 206, 86, 0.5)',
borderColor: 'rgba(255, 206, 86, 1)',
stack: 'Completed',
},
{
label: 'Medium',
data: [3, 4, 7],
borderWidth: 1,
backgroundColor: 'rgba(153, 102, 255, 0.5)',
borderColor: 'rgba(153, 102, 255, 1)',
stack: 'Completed',
},
],
},
interaction: {
intersect: false,
},
options: {
plugins: {
// Configuration of the datalabels plugin
datalabels: {
align: "start",
anchor: "start",
color: "black",
formatter: function(value, context) {
let ds = context.chart.data.datasets;
// Check if it's the first dataset
if (ds[context.datasetIndex - 1]) {
// Check if the dataset is in the same stack as the dataset before
if (
ds[context.datasetIndex - 1].stack ===
ds[context.datasetIndex].stack
) {
return "";
} else {
return ds[context.datasetIndex].stack;
}
} else {
return ds[context.datasetIndex].stack;
}
}
},
legend: {
// Since the labels defined below point only to single datasets,
// we use this to show/hide all datasets with the same label.
onClick: function(e, legendItem, legend) {
const ci = legend.chart;
const numberOfIndeces = ci.data.datasets.length;
let initIndex = legendItem.datasetIndex;
// Loop over all datasets corresponding to the label that has
// been clicked on.
while (initIndex < numberOfIndeces) {
let index = initIndex;
if (ci.isDatasetVisible(index)) {
ci.hide(index);
legendItem.hidden = true;
} else {
ci.show(index);
legendItem.hidden = false;
}
// 5 matches the number of different categories we have
// i.e., Blocker, High, Low, Critical, Medium.
initIndex += 5;
}
},
labels: {
// Manually override the labels returned.
// Failure to do this will lead to duplicated labels.
generateLabels: function(chart) {
return [{
text: 'Blocker',
fillStyle: 'rgba(255, 99, 132, 0.5)',
strokeStyle: 'rgba(255, 99, 132, 1)',
datasetIndex: 0,
lineWidth: 1,
hidden: false,
},
{
text: 'High',
fillStyle: 'rgba(54, 162, 235, 0.5)',
strokeStyle: 'rgba(54, 162, 235, 1)',
datasetIndex: 1,
lineWidth: 1,
hidden: false,
},
{
text: 'Low',
fillStyle: 'rgba(75, 192, 192, 0.5)',
strokeStyle: 'rgba(75, 192, 192, 1)',
datasetIndex: 2,
lineWidth: 1,
hidden: false,
},
{
text: 'Critical',
fillStyle: 'rgba(255, 206, 86, 0.5)',
strokeStyle: 'rgba(255, 206, 86, 1)',
datasetIndex: 3,
lineWidth: 1,
hidden: false,
},
{
text: 'Medium',
fillStyle: 'rgba(153, 102, 255, 0.5)',
strokeStyle: 'rgba(153, 102, 255, 1)',
datasetIndex: 4,
lineWidth: 1,
hidden: false,
},
]
}
}
}
},
scales: {
x: {
stacked: true,
ticks: {
callback: function(value, index, ticks) {
// Hide the default label
return ''
}
}
},
// Display the main label beneath the stack labels
x2: {
border: {
display: false
},
grid: {
display: false
}
},
y: {
stacked: true
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>
<canvas id="myChart"></canvas>
You will need to get rid of indexAxis: 'y',
in your code for the proper display of the axes.
Upvotes: 1