Show/hide 当外部为 shown/hidden 时,ChartJS 饼图中的所有嵌套数据
Show/hide All nested data in ChartJS Pie chart when outer is shown/hidden
我正在尝试在 ChartJS 3 中创建一个嵌套的 pie/doughnut 图表,但当使用图例隐藏其中一个外部部分时,我无法正确显示数据。
数据的第二个内环只是分割成更具体段的外环:
- 外部:
[541, 147, 8]
- 内部:
[300, 241, 100, 47, 8]
当用户隐藏 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>
我正在尝试在 ChartJS 3 中创建一个嵌套的 pie/doughnut 图表,但当使用图例隐藏其中一个外部部分时,我无法正确显示数据。
数据的第二个内环只是分割成更具体段的外环:
- 外部:
[541, 147, 8]
- 内部:
[300, 241, 100, 47, 8]
当用户隐藏 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>