图表 Js 折线图,点击填充,附有图例文本的完整信息

问题描述

我使用的是 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',data: [.0,.4],borderWidth: 1
    }]
  },options: {
    responsive: true,onClick : (event,items) =>{
        console.log("event",event);
    },}
});

areachart

解决方法

最后,我尝试使用一些 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,5,2],backgroundColor: "#ffe8e8",borderColor: ["#ffe8e8"],borderWidth: 1,},{
              lineTension: 0,label: "Data B",data: [12,17,2,6,8,4],backgroundColor: "#e2ffcb",borderColor: ["#e2ffcb"],label: "Data C",data: [15,23,9,7,10,11],backgroundColor: "#ffe689",borderColor: ["#ffe689"],});
      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,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,x1x2Pixcels.x1,y1,x1x2Pixcels.x2,y2
            );

            if (isBelow) {
              dataLable = isBelow ? dataALable : dataLable;
              if (i == 1) {
                var isBelowZeroLine = IsBelowTheLine(
                  curXPixcel,0
                );
                dataLable = isBelowZeroLine ? "" : dataLable;
              }
            } else break;
          }
        }
        return dataLable;
      }
      function IsBelowTheLine(x,y,x1,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>