Chart.js 在线性图表上拖动点

2022-01-22 00:00:00 charts javascript chart.js

我有一个使用

也许如果没有办法将拖放添加到点,将有一种技巧可以将具有绝对位置的滑块"放在图形上的点位置上.我也没有找到任何信息:(

解决方案

如果有人正在寻找不需要使用插件的解决方案,在原版 chart.js.

这是一个简单的工作示例 - 只需单击并拖动数据点

//一些要绘制的数据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];//全局变量var activePoint = null;变量画布=空;//在画布上下文中绘制折线图window.onload = 函数(){//用两个数据集绘制折线图var ctx = document.getElementById("canvas").getContext("2d");canvas = document.getElementById("canvas");window.myChart = Chart.Line(ctx, {数据: {标签:x_data,数据集:[{数据:y_data_1,标签:数据1",边框颜色:#3e95cd",填写:假},{数据:y_data_2,标签:数据2",边框颜色:#cd953e",填写:假}]},选项: {动画片: {持续时间:0},工具提示:{模式:'最近的'}}});//为画布元素设置指针事件处理程序canvas.onpointerdown = down_handler;canvas.onpointerup = up_handler;canvas.onpointermove = null;};功能down_handler(事件){//检查事件位置附近的数据点常量点 = window.myChart.getElementAtEvent(event, {intersect: false});if (points.length > 0) {//抓取最近的点,开始拖动活动点=点[0];canvas.onpointermove = move_handler;};};功能 up_handler(事件) {//释放抓取点,停止拖动活动点=空;canvas.onpointermove = null;};函数 move_handler(事件){//在图表数据中定位抓取点如果(活动点!= null){var data = activePoint._chart.data;var datasetIndex = activePoint._datasetIndex;//读取鼠标位置const helpers = Chart.helpers;var position = helpers.getRelativePosition(event, myChart);//将鼠标位置转换为图表 y 轴值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);//更新活动数据点的 y 值data.datasets[datasetIndex].data[activePoint._index] = yValue;window.myChart.update();};};//将值映射到其他坐标系函数映射(值,开始 1,停止 1,开始 2,停止 2){返回 start2 + (stop2 - start2) * ((value - start1)/(stop1 - start1))};

body {字体系列:Helvetica Neue、Arial、无衬线字体;文本对齐:居中;}.wrapper {最大宽度:800px;边距:50px 自动;}h1 {字体粗细:200;字体大小:3em;边距:0 0 0.1em 0;}h2 {字体粗细:200;字体大小:0.9em;边距:0 0 50px;颜色:#555;}一个 {边距顶部:50px;显示:块;颜色:#3e95cd;}

<!DOCTYPE html><html><!-- HEAD 元素:加载样式表和chart.js 库--><头><title>可拖动点</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"></头><!-- BODY 元素:创建画布并在其上渲染图表--><身体><!-- 容器中的画布元素--><div 类="包装器"><canvas id="canvas" width="1600" height="900"></canvas></div><!-- 调用外部脚本在画布上创建和渲染图表--><script src="script.js"></script></身体></html>

I have a simple linear chart built with Chart.js library.

And i want to allow user to drag points on chart for dynamically change data of it. I tied chartjs-plugin-draggable but it works for me only with annotations. I need graph exactly like this:

https://www.rgraph.net/canvas/docs/adjusting-line.html

But use new graph library in project is not good solution :(

Also i tried to play with dot event's.

UPDATE:

With angular i created something like this.

Maybe if there is no way to add drag&drop to points, there will be a hack to put "sliders" with absolute position on graph on points positions. I didn't find any info too :(

解决方案

In case anyone is looking for a solution that doesn't require the use of plugins, it's pretty straightforward to do it in vanilla chart.js.

Here's a simple working example - just click and drag a data point

// 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 two data sets
    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</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">
      <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>

相关文章