<!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>
结果如下: 输出 我期待这样的事情: 期待 我期待一个堆叠分组图表:例如:
X 轴:待办事项、进行中、完成
每个 x 轴标签有 4 个堆栈:[正在审核、正在进行、新建、已完成] 3 - 4
现在每个堆栈有 5 个数据点:[Blocked、High、Critical、Low、Medium] 4 - 5
您可以使用带组的堆叠条形图,它允许您拥有堆叠条形图并控制数据的分组方式。
使用这种方法,您将需要为每个堆栈中的每个数据点拥有不同的数据条目。这意味着您需要为“正在审核”、“进行中”、“新建”和“已完成”堆栈定义“已阻止”数据。
您还需要使用一个名为 chartjs-plugin-datalabels 的插件,它允许您标记不同的组/堆栈。
所包含代码的两个已知问题:
代码如下:
// 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>
您需要在代码中删除
indexAxis: 'y',
才能正确显示轴。