切换分组的图例元素时,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>