Текущее слияние точек с одной и той же осью x в одном ряду

В настоящее время я использую highstock для построения графика общего количества доступных товаров в зависимости от времени в течение дня (которое затем обновляется в режиме реального времени).

Если одновременно происходит два изменения общего количества предметов, в highstock я получаю вертикальную черту разницы:

Одновременное изменение оси Y

Итак, в моем примере изображения мы начинаем с 4299 вещей, затем удаляются 53 элемента и добавляются 50 (технически одновременно, но это две разные транзакции и две точки). С чистой разницей -3. (или, другими словами, я получаю {x: 5:44:15 и y: 4246, изменение: -53}, {x: 5:44:15, y: 4296, изменение: 50}).

Итак, мой вопрос: возможно ли в highstock объединить эти точки, чтобы избавиться от вертикальной полосы и использовать 4296 в качестве отображаемого значения? Я надеялся, что затем смогу использовать средство форматирования всплывающей подсказки, чтобы прокрутить «this.points» и отобразить изменение -53 и изменение 50 во всплывающей подсказке, чтобы пользователь мог видеть, что привело к чистому изменению -3.

Если это невозможно, я просто сам объединяю точки и передаю всю соответствующую информацию в точку, чтобы сгенерировать всплывающую подсказку (и внешний вид диаграммы), к которой я стремлюсь, но хотел посмотреть, смогу ли я просто использовать все функциональные возможности сначала highstock - и держите эти точки отдельно.

Спасибо!

Редактировать::

new Highcharts.StockChart({
                        chart : {
                            renderTo : 'realTimeChart',
                            zoomType: 'x',
                            backgroundColor: '#feffdd',
                            style: {
                                fontFamily: 'Segoe UI'
                            },
                            type: 'spline'
                        },

                        plotOptions: {
                            area: { animation: false },
                            arearange: { animation: false },
                            areaspline: { animation: false },
                            areasplinerange: { animation: false },
                            bar: { animation: false },
                            column: { animation: false },
                            columnrange: { animation: false },
                            gauge: { animation: false },
                            line: { animation: false },
                            pie: { animation: false },
                            scatter: { animation: false },
                            series: { animation: false },
                            spline: { animation: false }
                        },

                        xAxis: {
                            ordinal: false
                        },

                        tooltip: {
                            animation: false,
                            formatter: function() {
                                var p = '';

                                p += '<span style="font-size: 9px;">' + Highcharts.dateFormat('%A, %b %e, %Y %H:%M:%S', this.x) +'</span><br/>';
                                $.each(this.points, function(i, point){
                                    p += '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>'+ this.y +'</b>';
                                    if (point.point.where) {
                                        p += '<br />' + point.point.where + ' changed by ' + point.point.change + (point.point.who ? ' (' + point.point.who + ')' : '');
                                    }
                                });

                                return p;

                            }
                        },

                        rangeSelector: {
                            buttons: [{
                                count: 30,
                                type: 'minute',
                                text: '30M'
                            }, {
                                count: 1,
                                type: 'hour',
                                text: '1H'
                            }, {
                                count: 6,
                                type: 'hour',
                                text: '6H'
                            }, {
                                type: 'all',
                                text: 'Day'
                            }],
                            inputEnabled: false,
                            selected: 1
                        },

                        exporting: {
                            enabled: false
                        },

                        series : [{
                            name : 'Available',
                            data : data,
                            lineWidth: 1,
                            states: {
                                hover: {
                                    enabled: false
                                }
                            }
                        }]

Данные в формате, который я показал ранее, за исключением того, что x на самом деле в миллисекундах с эпохи:

data = [
        {x: 123456789, y: 2000, where: 'Location', change: 40, who: 'Joe'},
        {x: 123456789, y: 1960, where: 'Location', change: -40, who: 'Bob'},
        ...
    ];

person crowebird    schedule 19.11.2012    source источник
comment
Что вы пробовали? Покажите нам код. Как вы получаете/устанавливаете источник данных для highcharts?   -  person Shmiddty    schedule 19.11.2012
comment
Возможно, вы захотите заранее обработать эти данные, чтобы учесть это. HighCharts просто принимает данные, которые вы ему отправляете. Вы, конечно, можете сделать это в HighCharts, но он на самом деле не предназначен для этого, и вы будете писать гораздо больше кода, чем вам нужно. При этом вы могли бы сгруппировать данные (похоже) на секунду? Попробуй это.   -  person wergeld    schedule 19.11.2012
comment
Добавлен дополнительный код, чтобы показать настройку. @Shmiddty, это был скорее вопрос, возможно ли это, поскольку я знаю, как я мог бы объединить все это сам. Но если бы это было особенностью хайчартов, то я бы скорее использовал ее, чем сам реализовывал слияние точек.   -  person crowebird    schedule 19.11.2012
comment
@wergeld - да, похоже, мне придется сделать собственное слияние (технически за миллисекунду, а не за секунду). Но вы ответили на то, что я и думал, так что спасибо!   -  person crowebird    schedule 19.11.2012
comment
Вы можете использовать обычный трюк с javascript и использовать значения x в качестве ключей свойств в объекте, а значения y являются значениями свойств. Итак, перебирая данные, вы проверяете, есть ли что-то в этом ключе, если есть, вносите свои коррективы, в противном случае сбрасываете это и продолжаете.   -  person Shmiddty    schedule 19.11.2012


Ответы (1)


Просто хотел узнать, как я легко обошел проблему. Вместо размещения по секундам я решил сгруппировать очки вместе до ближайшей минуты с округлением в меньшую сторону (поэтому у меня есть блоки минут).

Затем для каждой точки я передал в качестве нового аргумента массив фактических точек, содержащихся в этом минутном блоке, и обновил значение y для этого минутного блока. Затем я использовал средство форматирования всплывающей подсказки, чтобы отобразить все изменения в этом минутном блоке с их фактическим временем изменения. Это дало мне более плавный график вместо всех этих жестких вертикальных точек для одной и той же оси x.

Чтобы легко изменить точку данных в определенной точке оси X, я сохранил отдельный массив местоположения минутного блока внутри массива series.data для хайчартов, таким образом, если мне нужно было обновить блок, я точно знал, где это временной ряд был.

Вот как я выполнил свою задачу: я создаю ссылочный массив:

var pointIndex = {};

Я создал исходный ряд данных из исторических данных за день (полученных через ajax):

var data = [];
var time = Math.floor(actual_time / 60000) * 60000;
pointIndex[time] = data.push({x: time, y: items_available, change: [{when: actual_time}]});

Таким образом, фактическое_время — это количество миллисекунд с начала эпохи (когда произошло четное изменение), затем я округляю его до ближайшей минуты, чтобы получить минутный блок времени, изменение — это аргумент, который будет содержать все фактические точки для отображения во всплывающей подсказке.

Поэтому, когда я добавляю новую точку, я проверяю, существует ли минутный блок, если нет, добавляю новую точку, в противном случае обновляю старую точку:

var time = (new Date()).getTime();
var point = Math.floor(time / 60000) * 60000;
if (pointIndex[point]) {
    var change = chart.series[0].data[pointIndex[point]].change;
    change.push({when: time});
    chart.series[0].data[pointIndex[point]].update({x: point, y: items_available, change: change});
} else {
    pointIndex[point] = chart.series[0].data.length;
    chart.series[0].addPoint({x: point, y: items_available, change: [{when: time}]}, false, false);
}

(Во всех случаях я действительно обновляю график после того, как закончу обновление точек.)

Надеюсь, это поможет любому, кто окажется в таком же положении!

Редактировать:: (забыл форматер):

tooltip: {
    animation: false,
    formatter: function() {
        var p = '';

        p += '<span style="font-size: 9px;">' + Highcharts.dateFormat('%A, %b %e, %Y %H:%M', this.x) +'</span><br/>';
        $.each(this.points, function(i, point){
            p += '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>'+ this.y +'</b>';
            if (point.point.change) {
                for(var j = 0; j < point.point.change.length; ++j) {
                    p += '<br />Change at: ' + new Date(point.point.change[j].when).toTimeString();
                }
            }
        });

        return p;

    }
}
person crowebird    schedule 20.11.2012