score:2

Accepted answer

i found the solution for it by myself. you have to use the chart bottom and top properties to map the correct size:

// read chart area
var chartarea = chart.chartarea;
var yvalue = map(position.y, chartarea.bottom, chartarea.top, ymin, ymax);

then the mapping is pixel perfect.

score:1

the answer was very useful but it took me quite a while to understand how to apply it.

therefore in case it is helpful to someone here's a simple working example.

in case it's not obvious, the three files below are respectively script.js, style.css and index.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>


Related Query

More Query from same tag