【问题标题】:Map event position to y axis value in chartjs line chart将事件位置映射到chartjs折线图中的y轴值
【发布时间】:2018-01-08 09:29:16
【问题描述】:

我目前正在修改Chart.js 折线图以使其具有交互性。这个想法是用户可以用手指移动图形的点。

以下是当前映射的示例:

chart-test.html

我已经管理它来读取事件并获取我必须修改的数据点:

// register pointer event
canvas.addEventListener('pointerdown', evt => {
    const points = interactiveChart.getElementsAtEventForMode(evt, 'index', {
        intersect: false
    });

    moveDataSetPoint(points, evt);
});

// change point relatively to y point
function moveDataSetPoint(points, evt)
{
    // read active data point
    var activePoint = points[0];
    var data = activePoint._chart.data;
    var datasetIndex = activePoint._datasetIndex;

    // read mouse position
    const helpers = Chart.helpers;
    var position = helpers.getRelativePosition(evt, interactiveChart);

    // calculate y axis value (ugly)
    // todo: map this with a chartjs method to map mouse inputs to yAxis values
    var yValue = map(position.y, window.myLine.height, 0, yMin, yMax);

    data.datasets[datasetIndex].data[activePoint._index] = yValue;
    window.myLine.update();
};

// attached the map function
function map(value, start1, stop1, start2, stop2) {
    return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1))
};

但问题是我的地图函数只是将y 指针位置映射到画布大小,然后是y 轴 minma​​x 值。

这是非常不准确的,我正在寻找一种方法,它可以从 指针事件 值中为我提供正确的 y 轴 值。

chartjs 中是否已经实现了某些功能?或者有没有一种方法可以只获取图表本身的大小,而没有围绕它的图例和边框(目前我正在映射到整个画布)?

【问题讨论】:

    标签: javascript chart.js interactive


    【解决方案1】:

    我自己找到了解决方案。您必须使用图表bottomtop 属性来映射正确的大小:

    // read chart area
    var chartArea = chart.chartArea;
    var yValue = map(position.y, chartArea.bottom, chartArea.top, yMin, yMax);
    

    那么映射是像素完美的。

    【讨论】:

      【解决方案2】:

      答案非常有用,但我花了很长时间才明白如何应用它。

      因此,如果它对某人有帮助,这里有一个简单的工作示例。

      如果不是很明显,下面三个文件分别是script.jsstyle.cssindex.html

      // some data to be plotted
      var x_data = [1500,1600,1700,1750,1800,1850,1900,1950,1999,2050];
      var y_data_1 = [86,114,106,106,107,111,133,221,783,2478];
      var y_data_2 = [2000,700,200,100,100,100,100,50,25,0];
      
      // globals
      var activePoint = null;
      var canvas = null;
      
      // draw a line chart on the canvas context
      window.onload = function () {
      
          // Draw a line chart with a single data set
          var ctx = document.getElementById("canvas").getContext("2d");
          canvas = document.getElementById("canvas");
          window.myChart = Chart.Line(ctx, {
              data: {
                  labels: x_data,
                  datasets: [
                      {
                          data: y_data_1,
                          label: "Data 1",
                          borderColor: "#3e95cd",
                          fill: false
                      },
                      {
                          data: y_data_2,
                          label: "Data 2",
                          borderColor: "#cd953e",
                          fill: false
                      }
                  ]
              },
              options: {
                  animation: {
                      duration: 0
                  },
                  tooltips: {
                      mode: 'nearest'
                  }
              }
          });
      
          // set pointer event handlers for canvas element
          canvas.onpointerdown = down_handler;
          canvas.onpointerup = up_handler;
          canvas.onpointermove = null;
      };
      
      function down_handler(event) {
          // check for data point near event location
          const points = window.myChart.getElementAtEvent(event, {intersect: false});
          if (points.length > 0) {
              // grab nearest point, start dragging
              activePoint = points[0];
              canvas.onpointermove = move_handler;
          };
      };
      
      function up_handler(event) {
          // release grabbed point, stop dragging
          activePoint = null;
          canvas.onpointermove = null;
      };
      
      function move_handler(event)
      {
          // locate grabbed point in chart data
          if (activePoint != null) {
              var data = activePoint._chart.data;
              var datasetIndex = activePoint._datasetIndex;
      
              // read mouse position
              const helpers = Chart.helpers;
              var position = helpers.getRelativePosition(event, myChart);
      
              // convert mouse position to chart y axis value 
              var chartArea = window.myChart.chartArea;
              var yAxis = window.myChart.scales["y-axis-0"];
              var yValue = map(position.y, chartArea.bottom, chartArea.top, yAxis.min, yAxis.max);
      
              // update y value of active data point
              data.datasets[datasetIndex].data[activePoint._index] = yValue;
              window.myChart.update();
          };
      };
      
      // map value to other coordinate system
      function map(value, start1, stop1, start2, stop2) {
          return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1))
      };
      body {
        font-family: Helvetica Neue, Arial, sans-serif;
        text-align: center;
      }
      
      .wrapper {
        max-width: 800px;
        margin: 50px auto;
      }
      
      h1 {
        font-weight: 200;
        font-size: 3em;
        margin: 0 0 0.1em 0;
      }
      
      h2 {
        font-weight: 200;
        font-size: 0.9em;
        margin: 0 0 50px;
        color: #555;
      }
      
      a {
        margin-top: 50px;
        display: block;
        color: #3e95cd;
      }
      <!DOCTYPE html>
      <html>
      
        <!-- HEAD element: load the stylesheet and the chart.js library -->
        <head>
          <title>Draggable Points Example</title>
          <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
          <link rel="stylesheet" type="text/css" href="style.css">
        </head>
      
        <!-- BODY element: create a canvas and render a chart on it -->
        <body>
      
          <!-- canvas element in a container -->
          <div class="wrapper">
            <h1>Draggable Points Example</h1>
            <h2>Click a data point and drag up/down</h2>
      
            <canvas id="canvas" width="1600" height="900"></canvas>
          </div>
      
          <!-- call external script to create and render a chart on the canvas -->
          <script src="script.js"></script>
        </body>
      
      </html>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-17
        • 1970-01-01
        • 2014-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多