Show/hide 当外部为 shown/hidden 时,ChartJS 饼图中的所有嵌套数据

Show/hide All nested data in ChartJS Pie chart when outer is shown/hidden

我正在尝试在 ChartJS 3 中创建一个嵌套的 pie/doughnut 图表,但当使用图例隐藏其中一个外部部分时,我无法正确显示数据。

数据的第二个内环只是分割成更具体段的外环:

当用户隐藏 GROUP1 时,正确的外部段被隐藏,但只有第一个内部段被隐藏,而不是第一个和第二个 (300 + 241 = 541)。所以我想知道如何正确地对这两个数据集进行分组,以便隐藏所有嵌套数据。

我在下面附上了演示该问题的示例。

var count = [541, 147, 8];
var countNested = [300, 241, 100, 47, 8];

var data = {
  labels: ["GROUP1", "GROUP2", "GROUP3"],
  datasets: [{
      data: count,
      backgroundColor: ["Red", "Green", "Blue"]
    },
    {
      data: countNested,
      backgroundColor: ["Red", "Red", "Green", "Green", "Blue"]
    }
  ]
}

const options = {
  type: 'doughnut',
  data: data,
  options: {}
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
const chart = new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="400" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.1/chart.js"></script>
</body>

我相信,对于这种情况没有简单的标准解决方案。

您需要将 legend.onClick 函数与 legend.labels.generateLabels 函数一起定义才能实现所需的行为。

For further details, see the Legend chapter of the Chart.js documentation.

请查看您修改后的可运行代码,看看它是如何完成的。

var count = [541, 147, 8];
var countNested = [300, 241, 100, 47, 8];

new Chart('chartJSContainer', {
  type: 'doughnut',
  data: {
    labels: ["GROUP1", "GROUP2", "GROUP3"],
    datasets: [{
        data: count,
        backgroundColor: ["Red", "Green", "Blue"]
      },
      {
        data: countNested,
        backgroundColor: ["Red", "Red", "Green", "Green", "Blue"]
      }
    ]
  },
  options: {
    responsive: false,
    plugins: {
      legend: {
        labels: {
          generateLabels: chart => chart.data.labels.map((l, i) => ({            
            text: l,
            index: i,
            fillStyle: chart.data.datasets[0].backgroundColor[i],
            strokeStyle: chart.data.datasets[0].backgroundColor[i],
            hidden: chart.getDatasetMeta(0).data[i].hidden
          })),
        },
        onClick: (event, legendItem, legend) => {
          let chart = legend.chart;
          let hidden = !chart.getDatasetMeta(0).data[legendItem.index].hidden;
          chart.getDatasetMeta(0).data[legendItem.index].hidden = hidden;
          let pointer = 0;
          chart.data.datasets[0].data.forEach((v, i) => {
            while (v > 0) {
              if (i == legendItem.index) {
                chart.getDatasetMeta(1).data[pointer].hidden = hidden;
              }
              v -= countNested[pointer++];
            }
          });
          chart.update();
        }
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
<canvas id="chartJSContainer" width="300"></canvas>