使用 zoomCallback,我如何 "snap" 缩放到现有的 x 值?
Using zoomCallback, how can I "snap" the zoom to existing x values?
我正在尝试使用 zoomCallback
函数来设置我的 dygrpahs 图表和地图图表之间的交互。我的 x 值是以秒为单位的时间戳,但由于采样率约为 100Hz,因此时间戳存储为 float 数字。
目标是当dygraphs图表放大时,新的x1
和x2
将用于提取一段GPS轨迹(纬度、经度点)。提取的轨迹将用于重新拟合地图边界 - 这在地图上看起来像 "zoom in"。
在我的 dygraphs 选项中,我指定了回调:
zoomCallback: function(x1,x2) {
let x1Index = graphHolder.getRowForX(x1);
let x2Index = graphHolder.getRowForX(x2);
// further code
}
但看起来缩放不是 "snapped" 到现有的时间戳点,因此 x1Index
和 x2Index
都是 null。只有当我缩小时,它们才会正确指向第 0 行和最后一行数据。
所以问题是 - 有没有一种方法可以使缩放仅捕捉到最近的现有 x 值,以便可以返回行号?或者,是否有其他方法可以满足我的要求?
感谢任何见解!
您可以通过 g.getValue(row, 0)
访问 x-axis 个值。由此,您可以进行线性扫描以找到范围内的第一行,或者(更高级但更快)使用二进制搜索。
这是一种进行线性扫描的方法:
const [x1, x2] = g.xAxisRange();
let letRow = null, highRow = null;
for (let i = 0; i < g.numRows(); i++) {
if (g.getValue(i, 0) >= x1) {
lowRow = i;
break;
}
}
for (let i = g.numRows() - 1; i >= 0; i--) {
if (g.getValue(i, 0) <= x2) {
highRow = i;
break;
}
}
const dataX1 = g.getValue(lowRow, 0);
const dataX2 = g.getValue(highRow, 0);
对于较大的数据集,您可能需要使用类似 lodash 的东西进行二进制搜索 _.sortedIndex
。
Update 下面是二分搜索的实现。没有关于边界上的确切行为的承诺(即它是否总是 returns 可见范围内的索引或包含可见范围的索引)。
function dygraphBinarySearch(g, x) {
let low = 0;
let high = g.numRows() - 1;
while (high > low) {
let i = Math.floor(low + (high - low) / 2);
const xi = g.getValue(i, 0);
if (xi < x) {
low = i + 1;
} else if (xi > x) {
high = i - 1;
} else {
return i;
}
}
return low;
}
function getVisibleDataRange(g) {
const [x1, x2] = g.xAxisRange();
let lowI = dygraphBinarySearch(g, x1);
let highI = dygraphBinarySearch(g, x2);
return [lowI, highI];
}
我正在尝试使用 zoomCallback
函数来设置我的 dygrpahs 图表和地图图表之间的交互。我的 x 值是以秒为单位的时间戳,但由于采样率约为 100Hz,因此时间戳存储为 float 数字。
目标是当dygraphs图表放大时,新的x1
和x2
将用于提取一段GPS轨迹(纬度、经度点)。提取的轨迹将用于重新拟合地图边界 - 这在地图上看起来像 "zoom in"。
在我的 dygraphs 选项中,我指定了回调:
zoomCallback: function(x1,x2) {
let x1Index = graphHolder.getRowForX(x1);
let x2Index = graphHolder.getRowForX(x2);
// further code
}
但看起来缩放不是 "snapped" 到现有的时间戳点,因此 x1Index
和 x2Index
都是 null。只有当我缩小时,它们才会正确指向第 0 行和最后一行数据。
所以问题是 - 有没有一种方法可以使缩放仅捕捉到最近的现有 x 值,以便可以返回行号?或者,是否有其他方法可以满足我的要求?
感谢任何见解!
您可以通过 g.getValue(row, 0)
访问 x-axis 个值。由此,您可以进行线性扫描以找到范围内的第一行,或者(更高级但更快)使用二进制搜索。
这是一种进行线性扫描的方法:
const [x1, x2] = g.xAxisRange();
let letRow = null, highRow = null;
for (let i = 0; i < g.numRows(); i++) {
if (g.getValue(i, 0) >= x1) {
lowRow = i;
break;
}
}
for (let i = g.numRows() - 1; i >= 0; i--) {
if (g.getValue(i, 0) <= x2) {
highRow = i;
break;
}
}
const dataX1 = g.getValue(lowRow, 0);
const dataX2 = g.getValue(highRow, 0);
对于较大的数据集,您可能需要使用类似 lodash 的东西进行二进制搜索 _.sortedIndex
。
Update 下面是二分搜索的实现。没有关于边界上的确切行为的承诺(即它是否总是 returns 可见范围内的索引或包含可见范围的索引)。
function dygraphBinarySearch(g, x) {
let low = 0;
let high = g.numRows() - 1;
while (high > low) {
let i = Math.floor(low + (high - low) / 2);
const xi = g.getValue(i, 0);
if (xi < x) {
low = i + 1;
} else if (xi > x) {
high = i - 1;
} else {
return i;
}
}
return low;
}
function getVisibleDataRange(g) {
const [x1, x2] = g.xAxisRange();
let lowI = dygraphBinarySearch(g, x1);
let highI = dygraphBinarySearch(g, x2);
return [lowI, highI];
}