开发者问题收集

页面上的两个 chartjs 图表抛出数据未定义错误

2020-09-23
772

我创建了以下问题 水平重叠条形图,而不是整个图形 ,并得到了友好的回答(我被建议创建一个新问题!)。虽然答案很有效 - 我在同一页面上有 2 个图表,但由于某种原因,它会引发 无法读取未定义的属性“数据” 错误。

我不想包含我的 2 个图表的全部内容,但移动条形的 afterUpdate 代码如下:

function(chart) {
    var datasets = chart.config.data.datasets;

    console.log(datasets);

    for (let iDs = 1; iDs < datasets.length; iDs++) {
        let dataset = datasets[iDs];

        // I added the following line however stacks the graph and doesn't display it correctly like the first
        if (typeof dataset._meta[0] !== 'undefined'){
            for (var i = 0; i < dataset._meta[0].data.length; i++) {
                let model = dataset._meta[0].data[i]._model;
                model.x += iDs * offset;
                model.controlPointNextX += iDs * offset;
                model.controlPointPreviousX += iDs * offset;
            }
        }
    }
}

我已经将 typeof 检查添加到至少可以呈现图表的代码中,但我希望两个图表以相同的方式运行,而添加 typeof 检查只会堆叠图表并忽略移动条形的代码。

这可以在以下小提琴中最好地看到: https://jsfiddle.net/ycpj7g8w/

1个回答

所描述的行为很奇怪,因为如果两个图表彼此独立创建,它们都可以正常工作。可以通过更改 afterUpdate 函数并使用图表的 .getDatasetMeta(index) 函数获取数据集的元数据来解决该问题。

afterUpdate: function(chart) {
  let datasets = chart.config.data.datasets;
  for (let iDs = 1; iDs < datasets.length; iDs++) {
    let meta = chart.getDatasetMeta(iDs);
    for (var i = 0; i < meta.data.length; i++) {
      let model = meta.data[i]._model;
      model.x += iDs * offset;
      model.controlPointNextX += iDs * offset;
      model.controlPointPreviousX += iDs * offset;
    }
  }
}

请查看以下修改后可运行的代码:

Chart.defaults.global.legend.labels.usePointStyle = true;
Chart.defaults.scale.gridLines.drawOnChartArea = false;

var offset = 6;

new Chart('graph_1', {
  "type": "bar",
  "data": {
    "labels": ["2020-08-01", "2020-09-01", "2020-10-01"],
    "datasets": [{
        "label": "Title test 1",
        "data": [30, 20, 60],
        "xAxisID": "bar-x-axis-1",
        "barThickness": 14,
        "backgroundColor": "rgba(241,213,157,1)",
        "borderColor": "rgba(241,213,157,1)",
        "pointBackgroundColor": "rgba(241,213,157,1)"
      },
      {
        "label": "Title test 2",
        "data": [30, 20, 60],
        "xAxisID": "bar-x-axis-2",
        "barThickness": 14,
        "backgroundColor": "rgba(237,141,120,1)",
        "borderColor": "rgba(237,141,120,1)",
        "pointBackgroundColor": "rgba(237,141,120,1)"
      },
      {
        "label": "Title test 3",
        "data": [30, 20, 60],
        "xAxisID": "bar-x-axis-3",
        "barThickness": 14,
        "backgroundColor": "rgba(120,199,212,1)",
        "borderColor": "rgba(120,199,212,1)",
        "pointBackgroundColor": "rgba(120,199,212,1)"
      }
    ]
  },
  "plugins": [{
    "afterUpdate": function(chart) {
      let datasets = chart.config.data.datasets;
      for (let iDs = 1; iDs < datasets.length; iDs++) {
        let meta = chart.getDatasetMeta(iDs);
        for (var i = 0; i < meta.data.length; i++) {
          let model = meta.data[i]._model;
          model.x += iDs * offset;
          model.controlPointNextX += iDs * offset;
          model.controlPointPreviousX += iDs * offset;
        }
      }
    }
  }],
  "curvature": 0.2,
  "options": {
    "legend": {
      "display": true,
      "position": "bottom"
    },
    "scales": {
      "yAxes": [{
        "ticks": {
          "beginAtZero": true,
          "stepSize": 25
        }
      }],
      "xAxes": [{
          "id": "bar-x-axis-3",
          "display": false
        },
        {
          "id": "bar-x-axis-2",
          "display": false,
          "offset": true
        },
        {
          "id": "bar-x-axis-1",
          "display": false,
          "offset": true
        }
      ]
    },
    "barRoundness": 0.5
  }
});

new Chart('graph_2', {
  "type": "bar",
  "data": {
    "labels": ["2020-06-01", "2020-07-01", "2020-08-01", "2020-09-01", "2020-10-01"],
    "datasets": [{
        "label": "Stage 1",
        "data": [30, 75, 60, 90],
        "xAxisID": "bar-x-axis-1",
        "barThickness": 14,
        "backgroundColor": "rgba(241,213,157,1)",
        "borderColor": "rgba(241,213,157,1)",
        "pointBackgroundColor": "rgba(241,213,157,1)"
      },
      {
        "label": "Stage 2",
        "data": [40, 66, 60, 90],
        "xAxisID": "bar-x-axis-2",
        "barThickness": 14,
        "backgroundColor": "rgba(237,141,120,1)",
        "borderColor": "rgba(237,141,120,1)",
        "pointBackgroundColor": "rgba(237,141,120,1)"
      },
      {
        "label": "Stage 3",
        "data": [50, 45, 60, 90],
        "xAxisID": "bar-x-axis-3",
        "barThickness": 14,
        "backgroundColor": "rgba(120,199,212,1)",
        "borderColor": "rgba(120,199,212,1)",
        "pointBackgroundColor": "rgba(120,199,212,1)"
      },
      {
        "label": "Stage 4",
        "data": [60, 35, 60, 90],
        "xAxisID": "bar-x-axis-4",
        "barThickness": 14,
        "backgroundColor": "rgba(5,114,159,1)",
        "borderColor": "rgba(5,114,159,1)",
        "pointBackgroundColor": "rgba(5,114,159,1)"
      },
      {
        "label": "Stage 5",
        "data": [70, 25, 60, 90],
        "xAxisID": "bar-x-axis-5",
        "barThickness": 14,
        "backgroundColor": "rgba(2,41,112,1)",
        "borderColor": "rgba(2,41,112,1)",
        "pointBackgroundColor": "rgba(2,41,112,1)"
      }
    ]
  },
  "plugins": [{
    "afterUpdate": function(chart) {
      let datasets = chart.config.data.datasets;
      for (let iDs = 1; iDs < datasets.length; iDs++) {
        let meta = chart.getDatasetMeta(iDs);
        for (var i = 0; i < meta.data.length; i++) {
          let model = meta.data[i]._model;
          model.x += iDs * offset;
          model.controlPointNextX += iDs * offset;
          model.controlPointPreviousX += iDs * offset;
        }
      }
    }
  }],
  "curvature": 0.2,
  "options": {
    "legend": {
      "display": true,
      "position": "bottom"
    },
    "scales": {
      "yAxes": [{
        "ticks": {
          "beginAtZero": true,
          "stepSize": 25
        }
      }],
      "xAxes": [{
          "id": "bar-x-axis-5",
          "display": false,
        },
        {
          "id": "bar-x-axis-4",
          "display": false,
          "offset": true
        },
        {
          "id": "bar-x-axis-3",
          "display": false,
          "offset": true
        },
        {
          "id": "bar-x-axis-2",
          "display": false,
          "offset": true
        },
        {
          "id": "bar-x-axis-1",
          "display": false,
          "offset": true
        }
      ]
    },
    "barRoundness": 0.5
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="graph_1"></canvas>
<canvas id="graph_2"></canvas>

Please note that when all charts contained on a page use the same plugin function, you don't have to repeat the code but can simply register it once through Chart.pluginService.register as shown in this answer .

uminder
2020-09-23