切换分组的图例元素时,ChartJS 绘图未按应有的方式显示
ChartJS plot not showing as it should be when toggling a grouped legend element
我有一个 ChartJS 可以绘制多条折线图和置信区间区域。问题是第一个带 CI 的分组折线图有问题,所以当我切换它时,其他组也隐藏了它们的区域。这很难用语言解释所以我记录下来并放上去here on youtube.
我目前的代码是这样的:
let predictData = [21,22,23,24,25,26,27,28];
let lowerCI80 = [20,21,22,23,24,25,26,27];
let upperCI80 = [22,23,24,25,26,27,28,29];
let lowerCI90 = [18,19,20,21,22,23,24,25];
let upperCI90 = [23,24,25,26,27,28,29,30];
const data = {
labels: [1,2,3,4,5,6,7,8],
datasets: [
{
label: "Lower_80%CI",
type: "line",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: low80Data,
yAxisID: "y",
xAxisID: "x",
},
{
label: "80% CI",
type: "line",
backgroundColor: "rgb(75, 192, 255)",
borderColor: "rgb(75, 192, 255)",
hoverBorderColor: "rgb(75, 192, 255)",
pointRadius: 0,
fill: false,
tension: 0,
data: predictData,
yAxisID: "y",
xAxisID: "x",
},
{
label: "Upper_80%CI",
type: "line",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: up80Data,
yAxisID: "y",
xAxisID: "x",
},
{
label: "Lower_90%CI",
type: "line",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: low90Data,
yAxisID: "y",
xAxisID: "x",
},
{
label: "90% CI",
type: "line",
backgroundColor: "rgb(255, 75, 75)",
borderColor: "rgb(255, 75, 75)",
hoverBorderColor: "rgb(255, 75, 75)",
pointRadius: 0,
fill: false,
tension: 0,
data: predictData,
yAxisID: "y",
xAxisID: "x",
},
{
label: "Upper_90%CI",
type: "line",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: up90Data,
yAxisID: "y",
xAxisID: "x",
},
],
};
const options = {
plugins: {
title: {
display: false,
},
legend: {
display: true,
position: "top",
labels: {
filter: function (item, chart) {
return !item.text.includes("_");
},
},
onClick: function (e, legendItem) {
// need to hide index -1 and index +1
var index = legendItem.datasetIndex;
var ci = this.chart;
var alreadyHidden =
ci.getDatasetMeta(index).hidden === null
? false
: ci.getDatasetMeta(index).hidden;
var meta_lo = ci.getDatasetMeta(index - 1);
var meta = ci.getDatasetMeta(index);
var meta_hi = ci.getDatasetMeta(index + 1);
if (!alreadyHidden) {
meta_lo.hidden = true;
meta.hidden = true;
meta_hi.hidden = true;
} else {
meta_lo.hidden = null;
meta.hidden = null;
meta_hi.hidden = null;
}
ci.update();
},
},
tooltip: {
mode: "index",
intersect: false,
},
},
hover: {
mode: "nearest",
intersect: false,
},
scales: {
xAxes: [
{
ticks: {
stepSize: 7, // This is not working as well(?)
fontColor: "white",
},
},
],
},
};
return <Line data={data} options={options} />
它不起作用的原因是您试图通过指定数据集索引来填充特定数据集。这没有用,因为该数据集已隐藏,因此不再填充。因此,您要么需要指定正确的数据集,要么对数据集使用相对填充。可以找到更多信息 here.
您的步长不起作用的原因是您的秤配置在 V2 中,而在 V3 中,秤的配置方式发生了变化。同样默认情况下,x 轴是一个类别轴,它没有 stepSize 属性.
对于 V2 和 V3 之间的所有变化,您可以阅读 migration guide
let predictData = [21, 22, 23, 24, 25, 26, 27, 28];
let low80Data = [20, 21, 22, 23, 24, 25, 26, 27];
let up80Data = [22, 23, 24, 25, 26, 27, 28, 29];
let low90Data = [18, 19, 20, 21, 22, 23, 24, 25];
let up90Data = [23, 24, 25, 26, 27, 28, 29, 30];
const data = {
labels: [1, 2, 3, 4, 5, 6, 7, 8],
datasets: [{
label: "Lower_80%CI",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
data: low80Data,
},
{
label: "80% CI",
backgroundColor: "rgb(75, 192, 255)",
borderColor: "rgb(75, 192, 255)",
hoverBorderColor: "rgb(75, 192, 255)",
pointRadius: 0,
data: predictData,
},
{
label: "Upper_80%CI",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: '-2',
data: up80Data,
},
{
label: "Lower_90%CI",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: '+2',
data: low90Data,
},
{
label: "90% CI",
backgroundColor: "rgb(255, 75, 75)",
borderColor: "rgb(255, 75, 75)",
hoverBorderColor: "rgb(255, 75, 75)",
pointRadius: 0,
data: predictData,
},
{
label: "Upper_90%CI",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
data: up90Data,
},
],
};
const options = {
plugins: {
title: {
display: false,
},
legend: {
display: true,
position: "top",
labels: {
filter: function(item, chart) {
return !item.text.includes("_");
},
},
onClick: function(e, legendItem) {
// need to hide index -1 and index +1
var index = legendItem.datasetIndex;
var ci = this.chart;
var alreadyHidden =
ci.getDatasetMeta(index).hidden === null ?
false :
ci.getDatasetMeta(index).hidden;
var meta_lo = ci.getDatasetMeta(index - 1);
var meta = ci.getDatasetMeta(index);
var meta_hi = ci.getDatasetMeta(index + 1);
if (!alreadyHidden) {
meta_lo.hidden = true;
meta.hidden = true;
meta_hi.hidden = true;
} else {
meta_lo.hidden = null;
meta.hidden = null;
meta_hi.hidden = null;
}
ci.update();
},
},
tooltip: {
mode: "index",
intersect: false,
},
},
hover: {
mode: "nearest",
intersect: false,
},
scales: {
x: {
type: 'linear',
ticks: {
stepSize: 7, // This is not working as well(?)
color: "white",
},
},
},
};
new Chart('chartJSContainer', {
type: 'line',
data: data,
options: options
})
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.2/chart.js"></script>
</body>
我有一个 ChartJS 可以绘制多条折线图和置信区间区域。问题是第一个带 CI 的分组折线图有问题,所以当我切换它时,其他组也隐藏了它们的区域。这很难用语言解释所以我记录下来并放上去here on youtube.
我目前的代码是这样的:
let predictData = [21,22,23,24,25,26,27,28];
let lowerCI80 = [20,21,22,23,24,25,26,27];
let upperCI80 = [22,23,24,25,26,27,28,29];
let lowerCI90 = [18,19,20,21,22,23,24,25];
let upperCI90 = [23,24,25,26,27,28,29,30];
const data = {
labels: [1,2,3,4,5,6,7,8],
datasets: [
{
label: "Lower_80%CI",
type: "line",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: low80Data,
yAxisID: "y",
xAxisID: "x",
},
{
label: "80% CI",
type: "line",
backgroundColor: "rgb(75, 192, 255)",
borderColor: "rgb(75, 192, 255)",
hoverBorderColor: "rgb(75, 192, 255)",
pointRadius: 0,
fill: false,
tension: 0,
data: predictData,
yAxisID: "y",
xAxisID: "x",
},
{
label: "Upper_80%CI",
type: "line",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: up80Data,
yAxisID: "y",
xAxisID: "x",
},
{
label: "Lower_90%CI",
type: "line",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: low90Data,
yAxisID: "y",
xAxisID: "x",
},
{
label: "90% CI",
type: "line",
backgroundColor: "rgb(255, 75, 75)",
borderColor: "rgb(255, 75, 75)",
hoverBorderColor: "rgb(255, 75, 75)",
pointRadius: 0,
fill: false,
tension: 0,
data: predictData,
yAxisID: "y",
xAxisID: "x",
},
{
label: "Upper_90%CI",
type: "line",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: 0,
tension: 0,
data: up90Data,
yAxisID: "y",
xAxisID: "x",
},
],
};
const options = {
plugins: {
title: {
display: false,
},
legend: {
display: true,
position: "top",
labels: {
filter: function (item, chart) {
return !item.text.includes("_");
},
},
onClick: function (e, legendItem) {
// need to hide index -1 and index +1
var index = legendItem.datasetIndex;
var ci = this.chart;
var alreadyHidden =
ci.getDatasetMeta(index).hidden === null
? false
: ci.getDatasetMeta(index).hidden;
var meta_lo = ci.getDatasetMeta(index - 1);
var meta = ci.getDatasetMeta(index);
var meta_hi = ci.getDatasetMeta(index + 1);
if (!alreadyHidden) {
meta_lo.hidden = true;
meta.hidden = true;
meta_hi.hidden = true;
} else {
meta_lo.hidden = null;
meta.hidden = null;
meta_hi.hidden = null;
}
ci.update();
},
},
tooltip: {
mode: "index",
intersect: false,
},
},
hover: {
mode: "nearest",
intersect: false,
},
scales: {
xAxes: [
{
ticks: {
stepSize: 7, // This is not working as well(?)
fontColor: "white",
},
},
],
},
};
return <Line data={data} options={options} />
它不起作用的原因是您试图通过指定数据集索引来填充特定数据集。这没有用,因为该数据集已隐藏,因此不再填充。因此,您要么需要指定正确的数据集,要么对数据集使用相对填充。可以找到更多信息 here.
您的步长不起作用的原因是您的秤配置在 V2 中,而在 V3 中,秤的配置方式发生了变化。同样默认情况下,x 轴是一个类别轴,它没有 stepSize 属性.
对于 V2 和 V3 之间的所有变化,您可以阅读 migration guide
let predictData = [21, 22, 23, 24, 25, 26, 27, 28];
let low80Data = [20, 21, 22, 23, 24, 25, 26, 27];
let up80Data = [22, 23, 24, 25, 26, 27, 28, 29];
let low90Data = [18, 19, 20, 21, 22, 23, 24, 25];
let up90Data = [23, 24, 25, 26, 27, 28, 29, 30];
const data = {
labels: [1, 2, 3, 4, 5, 6, 7, 8],
datasets: [{
label: "Lower_80%CI",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
data: low80Data,
},
{
label: "80% CI",
backgroundColor: "rgb(75, 192, 255)",
borderColor: "rgb(75, 192, 255)",
hoverBorderColor: "rgb(75, 192, 255)",
pointRadius: 0,
data: predictData,
},
{
label: "Upper_80%CI",
backgroundColor: "rgb(75, 192, 255, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: '-2',
data: up80Data,
},
{
label: "Lower_90%CI",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
fill: '+2',
data: low90Data,
},
{
label: "90% CI",
backgroundColor: "rgb(255, 75, 75)",
borderColor: "rgb(255, 75, 75)",
hoverBorderColor: "rgb(255, 75, 75)",
pointRadius: 0,
data: predictData,
},
{
label: "Upper_90%CI",
backgroundColor: "rgb(255, 75, 75, 0.3)",
borderColor: "transparent",
pointRadius: 0,
data: up90Data,
},
],
};
const options = {
plugins: {
title: {
display: false,
},
legend: {
display: true,
position: "top",
labels: {
filter: function(item, chart) {
return !item.text.includes("_");
},
},
onClick: function(e, legendItem) {
// need to hide index -1 and index +1
var index = legendItem.datasetIndex;
var ci = this.chart;
var alreadyHidden =
ci.getDatasetMeta(index).hidden === null ?
false :
ci.getDatasetMeta(index).hidden;
var meta_lo = ci.getDatasetMeta(index - 1);
var meta = ci.getDatasetMeta(index);
var meta_hi = ci.getDatasetMeta(index + 1);
if (!alreadyHidden) {
meta_lo.hidden = true;
meta.hidden = true;
meta_hi.hidden = true;
} else {
meta_lo.hidden = null;
meta.hidden = null;
meta_hi.hidden = null;
}
ci.update();
},
},
tooltip: {
mode: "index",
intersect: false,
},
},
hover: {
mode: "nearest",
intersect: false,
},
scales: {
x: {
type: 'linear',
ticks: {
stepSize: 7, // This is not working as well(?)
color: "white",
},
},
},
};
new Chart('chartJSContainer', {
type: 'line',
data: data,
options: options
})
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.2/chart.js"></script>
</body>