我目前正在修改Chart.js折线图以实现互动。这个想法是用户可以用手指移动图形的点。
以下是使用当前映射的示例:
我已经设法读取事件并获取我必须修改的数据点:
// 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轴 min 和最大值。
这是非常不准确的,我正在寻找一种方法,它从指针事件值中提供正确的 y轴值。
chartjs中是否已经实现了一些功能?或者是否有一种方法可以获得图表本身的大小,而没有图例周围的边界和边框(目前我正在映射到整个画布)?
答案 0 :(得分:1)
我自己找到了解决方案。您必须使用图表bottom
和top
属性来映射正确的尺寸:
// read chart area
var chartArea = chart.chartArea;
var yValue = map(position.y, chartArea.bottom, chartArea.top, yMin, yMax);
然后映射就像素完美。
答案 1 :(得分:0)
答案非常有用,但是花了我一段时间才了解如何应用。
因此,如果这对某人有帮助,下面是一个简单的工作示例。
如果不太明显,下面的三个文件分别为script.js
,style.css
和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>