Chart.js同步图例在多个图表上切换
有一些解决方案可以使用legend onClick在单击的图表上打开/关闭所有其他数据集的可见性,但是如果多个图表具有相同的标签/图例,我需要一种方法在多个图表上同步此切换。例如,我有6个图表显示了关于相同数据的不同信息。然而,并非所有的图表都有所有的数据集。一个可能有5个数据集,另一个有3个,以此类推。它们也可能不会以相同的顺序出现 目标是能够在一个图表上单击一个图例项,并在所有图表上切换相同的项Chart.js同步图例在多个图表上切换,chart.js,Chart.js,有一些解决方案可以使用legend onClick在单击的图表上打开/关闭所有其他数据集的可见性,但是如果多个图表具有相同的标签/图例,我需要一种方法在多个图表上同步此切换。例如,我有6个图表显示了关于相同数据的不同信息。然而,并非所有的图表都有所有的数据集。一个可能有5个数据集,另一个有3个,以此类推。它们也可能不会以相同的顺序出现 目标是能够在一个图表上单击一个图例项,并在所有图表上切换相同的项 因为我没有找到一个现有的解决方案,所以我发布了这篇文章。为了做到这一点,我将所有图表放在一个全局
因为我没有找到一个现有的解决方案,所以我发布了这篇文章。为了做到这一点,我将所有图表放在一个全局变量中,并通过它们循环,以通过legendItem.text而不是legendItem.datasetindex匹配dataset,因为标签可能存在,也可能不存在,甚至在其他图表上处于相同的索引位置 以下是我如何创建/替换多个图表: 下面是legend onClick切换解决方案:
var config = {
type: type,
data: {
labels: labels,
datasets: datasets
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}]
},
legend: {
position: 'right',
onClick: function (e, legendItem) {
var text = legendItem.text;
Object.keys(charts).forEach(function (id) {
// loop through the charts
var ci = charts[id].chart
var cindex = (function () {
var match = null;
ci.legend.legendItems.forEach(function (item) {
if (item.text == text) {
// get index for legend.text that matches clicked legend.text
match = item.datasetIndex;
}
});
return match;
})();
if (cindex !== null) {
// if there's a match
var alreadyHidden = (ci.getDatasetMeta(cindex).hidden === null) ? false : ci.getDatasetMeta(cindex).hidden;
ci.data.datasets.forEach(function (e, i) {
var meta = ci.getDatasetMeta(i);
if (i !== cindex) {
if (!alreadyHidden) {
meta.hidden = meta.hidden === null ? !meta.hidden : null;
} else if (meta.hidden === null) {
meta.hidden = true;
}
} else if (i === cindex) {
meta.hidden = null;
}
});
ci.update();
}
});
}
}
}
};
在使用Chris的答案后,我创建了一个简化的解决方案
var config = {
type: type,
data: {
labels: labels,
datasets: datasets
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}]
},
legend: {
position: 'right',
onClick: function (e, legendItem) {
var text = legendItem.text;
Object.keys(charts).forEach(function (id) {
// loop through the charts
var ci = charts[id].chart
ci.legend.legendItems.forEach(function (item) {
if (item.text == text) {
ci.options.legend.onClick.call(chart.legend, null, item);
ci.update();
}
});
});
}
}
}
};
使用此解决方案的好处是,它将调用已添加到任何图表图例中的任何自定义onClick处理程序。如果有人正在寻找将饼图图例与折线图图例同步的方法,请尝试此方法。如果图表的类型相同,也可以正常工作:
onClick: function(e, legendItem) {
// Save name of clicked label, for later comparison
var legendName = legendItem.text;
// Iterate through global charts array
Object.keys(myCharts).forEach(function(id) {
// Assign shorthand variable to address chart easier
var chrt = myCharts[id];
// Determine chart type
var chartType = chrt.config.type;
// Iterate through each legend in the chart
chrt.legend.legendItems.forEach(function(item) {
// If legend name matches clicked label
if (item.text == legendName) {
if (chartType == 'pie') { // If pie chart
if (chrt.getDatasetMeta(0).data[item.index].hidden === true) chrt.getDatasetMeta(0).data[item.index].hidden = false;
else if (chrt.getDatasetMeta(0).data[item.index].hidden === false) chrt.getDatasetMeta(0).data[item.index].hidden = true;
} else if (chartType == 'line') { // If line chart
if (chrt.getDatasetMeta(item.datasetIndex).hidden === true) chrt.getDatasetMeta(item.datasetIndex).hidden = null;
else if (chrt.getDatasetMeta(item.datasetIndex).hidden === null) chrt.getDatasetMeta(item.datasetIndex).hidden = true;
}
// Trigger chart update
chrt.update();
}
});
});
将此onClick函数放置在选项的图例部分,就像您在其他答案中看到的一样
我的折线图是一种日常趋势,而饼图则比较了整个范围内的总数。
当然,图表的标签必须使用相同的名称才能起作用
与其他解决方案一样,您必须将两个图表存储在一个全局变量中,如:
window.myCharts['pieChart1']
window.myCharts['lineChart1']
由于隐藏数据集以及在整个数据集中获取其索引因图表类型而异,因此此函数将检查图表类型并相应地执行操作。
还要注意,对于饼图,隐藏设置为true或false,但是对于折线图,隐藏设置为true或null,谢谢chart.js。
我相信您可以将其扩展到其他图表类型,但我只为“直线”和“饼图”图表设置了它。调用自定义onClick,调用相同的东西,导致无休止的循环和浏览器窗口崩溃。另外,chart.legend未定义。