1

我正在尝试在Zoom/onPan 上获取更多数据到我的chartjs 折线图(或使用缓存的一些备份数据),但是这样做有很多问题。

我的初始代码库非常复杂,我无法在这里完全复制,但我会分享我已经尝试过的内容。

第一种解决方案: 此处提到的Chartjs-plugin-zoom共享onZoom和回调, 但这些回调不提供任何上下文(图表、x、y),并且在平移/缩放时调用,甚至不正确。onPan

此 PR 解决了一些问题,但尚未合并:链接

第二种解决方案:我试图在beforeUpdate回调中获取图表 js 中的更改数据,但这也给我带来了很多问题。默认情况下,我在图表中显示大约 1000 个数据点,并且由于我的图表每秒更新一次,所以我要做的是备份数据,其中包含 1000 个数据点之外的传递数据点,所以当有人 zoomOut 我正在检查左右的坐标,如果这些改变(增加)我想在beforeUpdate回调中增加数据集中的数据。

scales: {
    xAxes: [{
                    id: 'x-axis-0',
                    type: 'time',
                    beforeUpdate: function (chart) {
                        const scale = chart.chart.scales['x-axis-0']
                        if (scale.margins) {
                            const left = scale.getValueForPixel(scale.left)
                            const right = scale.getValueForPixel(scale.right)
                            const diffSec = (right - left) / 1000;
                            if (diffSec < 240) {
                                chart.chart.options.scales.xAxes[0].time.unit = 'second'
                            } else if (diffSec < 4*3600) {
                                chart.chart.options.scales.xAxes[0].time.unit = 'minute'
                            } else {
                                chart.chart.options.scales.xAxes[0].time.unit = 'minute'
                                chart.chart.options.scales.xAxes[0].time.stepSize = 10
                            }
                        }
// Ignore this if condition it is just for testing/debugging
                        if (chart.chart.data.labels.length > 1) {
                            // there are three line in graph
                            chart.chart.data.datasets[0].data = getMinArray(diffSec)
                            chart.chart.data.datasets[1].data = getAvgArray(diffSec)
                            chart.chart.data.datasets[2].data = getMaxArray(diffSec)
                            chart.chart.data.labels = getLabels(diffSec)
                            chart.update()
                          }
                    }
    }

在第二种方法中,我收到更多错误,例如:

TypeError:无法读取未定义的属性“隐藏”

你有第三种解决方案吗?请把它扔到下面。

编辑:我尝试过不同的版本

"chart.js": "2.8.0",
"chartjs-plugin-zoom": "^0.7.0",

似乎第一个解决方案现在正在工作,但还有另一个问题:

  • onZoom缩放时被调用,而不是

    Function called once zooming is completed

    自述文件中所述,因此这不会真正有助于从 API 获取数据。

4

2 回答 2

0

Chartjs-plugin-zoom 共享此处提到的 onZoom 和 onPan 回调,但这些回调不提供任何上下文(图表、x、y)

实际上提供了上下文。使用包含图表的对象调用它,因此您可以执行以下操作:

function callback(context) {
  console.log('Here is the chart: ' + context.chart);
}
于 2019-06-23T14:14:14.587 回答
0

我找到了解决方案,它在beforeUpdate回调中运行良好。

我的图中有 1-3 个数据集,该解决方案适用于您想要放置的任意数量的数据集,但仅适用于在图中具有和使用的时间序列。allLabelsallData

我有一个更复杂的用例,但在这里共享最简单的代码beforeUpdatefilterData代码:


function filterData(chartInstance, leftLegendTime) {

    let diff = chartInstance.data.labels[0].getTime() - leftLegendTime
    // Check min 10 sec difference between graph and zoomed out graph to get safe from over updates
    if (!chartInstance.data.labels || diff === 0 || diff <= 10000) return

    let allLabels = chartInstance.data.datasets[0].allLabels

    // Matching graph's left axis start...
    let leftIndex = allLabels.map(
        (elem) => parseInt(elem.getTime()/1000)
    ).indexOf(parseInt(leftLegendTime/1000))

    if (leftIndex === -1) return;

    chartInstance.data = {...chartInstance.data, labels: allLabels.slice(leftIndex)}

    for (let i = 0;i < chartInstance.data.datasets.length; i++) {
        chartInstance.data.datasets[i] = {
            ...chartInstance.data.datasets[i],
            data: chartInstance.data.datasets[i].allData.slice(leftIndex)
        }
    }

    chartInstance.update()
}


// ...in graphOptions:
scales: {
        xAxes: [{
        id: 'x-axis-0',
        type: 'time',
        beforeUpdate: function (chart) {
        const scale = chart.chart.scales['x-axis-0']
        if (scale.margins) {
            const left = scale.getValueForPixel(scale.left)
            filterData(chart.chart, left._d.getTime())
        }
     }
}],
zoom: {
    enabled: true,
    drag: false, // cannot have drag-to-zoom and pan at once
    mode: 'x',
    rangeMax: {
        x: new Date(Date.now() + 1000)
    },
    rangeMin: {
        x: new Date(Date.now() - 900 * 1000) // eg. to show max history...
    }
}
于 2019-06-27T05:25:01.790 回答