Получить больше данных для линейного графика по вопросам Zoom / OnPan - PullRequest
1 голос
/ 21 июня 2019

Я пытаюсь извлечь больше данных в мою линейную диаграмму chartjs (или использовать некоторые кэшированные резервные данные) onZoom / onPan, но у меня много проблем с этим.

Моя исходная кодовая база очень сложна, и я не могу скопировать ее здесь полностью, но я поделюсь тем, что уже пробовал.

1-е решение: Chartjs-plugin-zoom разделяет onZoom и onPan обратные вызовы, как упомянуто здесь но они не предоставляют никакого контекста (chart, x, y) с этими обратными вызовами и вызовами при панорамировании / масштабировании, и это даже неправильно.

Этот PR решает несколько проблем, но еще не объединен: Ссылка

2-е решение: Я пытаюсь получить данные изменений в диаграмме js в beforeUpdate обратном вызове, но это также вызывает много проблем. По умолчанию я показываю около 1000 точек данных на графике, и, поскольку мой график обновляется каждую секунду, я пытаюсь создать резервную копию данных, которые будут содержать переданные точки данных за пределами 1000 точек данных, поэтому, когда кто-то увеличивает масштаб, я проверяю координаты влево и вправо, и если они изменяются (увеличение), я хочу увеличить данные в наборе данных в 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: Невозможно прочитать свойство 'hidden' неопределенного

У вас есть 3-е решение? , пожалуйста, киньте его ниже.

РЕДАКТИРОВАТЬ: Я пробовал с разными версиями

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

Кажется, что 1-е решение сейчас работает, но есть другая проблема:

  • onZoom вызывается при увеличении, а не

    Function called once zooming is completed

    как упоминалось в Readme , так что это не очень поможет при извлечении данных из API.

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

Я нашел решение, и оно хорошо работает в beforeUpdate callBack.

У меня есть 1-3 набора данных в моих графиках, и решение работает для любого количества наборов данных, которые вы хотите поместить Но только для временного ряда с использованием allLabels и allData для использования в графе.

У меня более сложный вариант использования, но я делюсь простейшим кодом здесь для beforeUpdate и filterDataкод:


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...
    }
}
0 голосов
/ 23 июня 2019

Chartjs-plugin-zoom совместно использует обратные вызовы onZoom и onPan, как упомянуто здесь, но они не предоставляют никакого контекста (chart, x, y) с этими обратными вызовами

Там на самом деле предоставляется контекст. Он вызывается с объектом, содержащим диаграмму, поэтому вы можете сделать:

function callback(context) {
  console.log('Here is the chart: ' + context.chart);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...