首页 > 解决方案 > 使用 zoomCallback,我如何将缩放“捕捉”到现有的 x 值?

问题描述

我正在尝试使用该zoomCallback功能来设置我的 dygrpahs 图表和地图图表之间的交互。我的 x 值是以秒为单位的时间戳,但由于采样率约为 100Hz,时间戳存储为浮点数

目标是,当放大 dygraphs 图表时,新的x1x2将用于提取一条 GPS 轨迹(纬度、经度点)。提取的轨迹将用于重新拟合地图边界 - 这看起来像地图上的“放大”。

在我的 dygraphs 选项中,我指定了回调:

zoomCallback: function(x1,x2) {
  let x1Index = graphHolder.getRowForX(x1);
  let x2Index = graphHolder.getRowForX(x2);
  // further code
}

但看起来缩放没有“捕捉”到现有的时间戳点,所以x1Index两者x2Index都是null。只有当我缩小时,它们才会正确指向第 0 行和最后一行数据。

所以问题是 - 有没有办法让缩放只捕捉到最近的现有 x 值,以便可以返回行号?或者,有没有其他方法可以做我想做的事?

感谢您的任何见解!

标签: callbackdygraphs

解决方案


您可以通过 访问 x 轴值g.getValue(row, 0)。从此,您可以进行线性扫描以查找范围中的第一行,或者(更高级但更快)使用二进制搜索。

这是进行线性扫描的一种方法:

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

更新这是一个二进制搜索实现。没有关于边界上的确切行为的承诺(即它是否总是返回可见范围内的索引或包含可见范围的索引)。

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];
}

推荐阅读