Chart Js 折线图,单击时填充并包含其图例文本的完整信息

Chart Js Line chart with fill on click with full information of its legend text

我正在使用 chart.js 2.9.3. 我在选项中使用了 onClick 处理程序以及 getElementAtEvent 来实现我的目标想要,但我得到了项目 empty 数组,并且事件没有有关被单击区域的信息。单击每个点都可以正常工作,但是单击整条线的区域并不能提供太多信息。

这是我的图表的代码片段。

var chart_canvas = document.getElementById("myChart");
var stackedLine = new Chart(chart_canvas, {
  type: 'line',
  data: {
    labels: ["0.0", "0.2", "0.4", "0.6", "0.8", "1.0"],
    fill: true,
    datasets: [{
      label: 'One',
      pointRadius: 3,
      data: [.5, .3, .2, .1, .4, .3],
      borderWidth: 1
    }, {
      label: 'Two',
      pointRadius: 3,
      data: [.0, .1, .2, .4, .1, .4],
      borderWidth: 1
    }]
  },
  options: {
    responsive: true,
    onClick : (event, items) =>{
        console.log("event",event);
    },    
  }
});

最后我尝试使用一些 DOM 操作来解决这个问题,通过单击折线图每个填充区域的区域来获取信息。 示例在这里:

https://codepen.io/amiablesyed/pen/RwKxaqE

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.js"></script>
  </head>
  <body>
    <div style="background-color: gainsboro">
      Data:<span id="Data"></span>
    </div>
    <div style="width: 500px; height: 400px">
      <canvas id="mainChart" width="700" height="400"> </canvas>
    </div>

    <script>
      var ctx = document.getElementById("mainChart").getContext("2d");
      var myChart = new Chart(ctx, {
        type: "line",
        data: {
          labels: [
            "Red",
            "Blue",
            "Yellow",
            "Green",
            "Purple",
            "Orange",
            "Pink",
            "Black",
            "Grey",
          ],
          datasets: [
            {
              lineTension: 0,
              label: "Data A",
              data: [11, 12, 1, 3, 1, 1, 3, 5, 2],
              backgroundColor: "#ffe8e8",

              borderColor: ["#ffe8e8"],
              borderWidth: 1,
            },
            {
              lineTension: 0,
              label: "Data B",
              data: [12, 17, 3, 5, 2, 3, 6, 8, 4],
              backgroundColor: "#e2ffcb",

              borderColor: ["#e2ffcb"],
              borderWidth: 1,
            },
            {
              lineTension: 0,
              label: "Data C",
              data: [15, 23, 6, 9, 3, 8, 7, 10, 11],
              backgroundColor: "#ffe689",

              borderColor: ["#ffe689"],
              borderWidth: 1,
            },
          ],
        },
      });
      document
        .getElementById("mainChart")
        .addEventListener("click", function (e) {
          areaClick(e);
        });
      function areaClick(e) {
        if (!myChart.scales["y-axis-0"]._gridLineItems) return;
        var gridLineH = myChart.scales["y-axis-0"]._gridLineItems[0];
        var lenH = myChart.scales["y-axis-0"]._gridLineItems.length;
        var width = gridLineH.x2 - gridLineH.x1;
        var yMax = myChart.scales["y-axis-0"].max;
        var yMaxPixcel = myChart.scales["y-axis-0"].bottom - gridLineH.y1;

        var gridLineV = myChart.scales["x-axis-0"]._gridLineItems[0];
        var lenV = myChart.scales["x-axis-0"]._gridLineItems.length;
        var height = gridLineV.y2 - gridLineV.y1;
        var xMax = myChart.scales["x-axis-0"].maxIndex;

        var scaleX = width / (lenV - 1);
        var scaleY = height / (lenH - 1);
        var yPixcel =
          yMaxPixcel - (e.pageY - e.target.offsetTop - gridLineH.y1);
        var yVal = yMax * (yPixcel / yMaxPixcel);
        console.log(yVal);
        var curXPixcel = e.pageX - e.target.offsetLeft - gridLineH.x1;
        var xVal = Math.floor(curXPixcel / scaleX);
        var xAxis = myChart.scales["x-axis-0"];
        var label = "Others";

        if (xVal < xAxis.maxIndex && xVal >= xAxis.minIndex) {
          var x1x2Pixcels = getx1x2Pixcels(xVal, gridLineH.x1);
          document.getElementById("Data").innerText = getDataLable(
            xVal,
            yVal,
            x1x2Pixcels,
            curXPixcel
          );
        }
      }
      function getx1x2Pixcels(xVal, offset) {
        var x1x2 = {};
        x1x2.x1 =
          myChart.scales["x-axis-0"]._gridLineItems[xVal].x1 - offset + 0.5;
        x1x2.x2 =
          myChart.scales["x-axis-0"]._gridLineItems[xVal + 1].x1 - offset + 0.5;
        return x1x2;
      }
      function getDataLable(xVal, yVal, x1x2Pixcels, curXPixcel) {
        var datasetes = myChart.config.data.datasets;
        var dataLable = "";
        if (datasetes.length > 1) {
          for (var i = datasetes.length; i > 0; i--) {
            if (myChart.getDatasetMeta(i - 1).hidden) continue;
            var dataA = datasetes[i - 1];
            var dataALable = dataA.label;
            var y1 = dataA.data[xVal];
            var y2 = dataA.data[xVal + 1];
            var isBelow = IsBelowTheLine(
              curXPixcel,
              yVal,
              x1x2Pixcels.x1,
              y1,
              x1x2Pixcels.x2,
              y2
            );

            if (isBelow) {
              dataLable = isBelow ? dataALable : dataLable;
              if (i == 1) {
                var isBelowZeroLine = IsBelowTheLine(
                  curXPixcel,
                  yVal,
                  x1x2Pixcels.x1,
                  0,
                  x1x2Pixcels.x2,
                  0
                );
                dataLable = isBelowZeroLine ? "" : dataLable;
              }
            } else break;
          }
        }
        return dataLable;
      }
      function IsBelowTheLine(x, y, x1, y1, x2, y2) {
        var v1 = [x2 - x1, y2 - y1];
        var v2 = [x2 - x, y2 - y];
        var xp = v1[0] * v2[1] - v1[1] * v2[0];
        return xp >= 0;
      }
    </script>
  </body>
</html>