堆叠分组图表任务状态条形图

问题描述 投票:0回答:1
<!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

chart.js stacked-chart grouped-bar-chart
1个回答
0
投票

您可以使用带组的堆叠条形图,它允许您拥有堆叠条形图并控制数据的分组方式。

使用这种方法,您将需要为每个堆栈中的每个数据点拥有不同的数据条目。这意味着您需要为“正在审核”、“进行中”、“新建”和“已完成”堆栈定义“已阻止”数据。

您还需要使用一个名为 chartjs-plugin-datalabels 的插件,它允许您标记不同的组/堆栈。

所包含代码的两个已知问题:

  1. 当文本隐藏时,单击图例不会删除图例文本。
  2. 当第一个数据集元素隐藏时,堆栈标签消失。

代码如下:

// 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',
才能正确显示轴。

© www.soinside.com 2019 - 2024. All rights reserved.