Как я могу добавить графики / данные в рикшу с d3.js?

Вот что у меня есть:

http://jsfiddle.net/bozdoz/Q6A3L/

rickshaw d3.js graph

Код для фоновых полос:

maxData = 80000000;
maxHeight = 250;
var yScale = d3.scale.linear().
  domain([0, maxData]). // your data minimum and maximum
  range([0, maxHeight]); // the pixels to map to, e.g., the height of the diagram.

var riskpoints = [62000000,48000000,30000000];
var rectDemo = d3.select("#chart").
    append("svg:svg").
    attr("width", 400).
    attr("height", maxHeight).
    attr('class','risk');

rectDemo.append("svg:rect").
    attr("x",0).
    attr("y", maxHeight - yScale(riskpoints[0])).
    attr("height", yScale(riskpoints[0]) - yScale(riskpoints[1])).
    attr("width", '100%').
    attr("fill", "rgba(0,100,0,.3)");

rectDemo.append("svg:rect").
    attr("x",0).
    attr("y", maxHeight - yScale(riskpoints[1])).
    attr("height", yScale(riskpoints[1]) - yScale(riskpoints[2])).
    attr("width", '100%').
    attr("fill", "rgba(100,100,0,.3)");

rectDemo.append("svg:rect").
    attr("x",0).
    attr("y", maxHeight - yScale(riskpoints[2])).
    attr("height", yScale(riskpoints[2])).
    attr("width", '100%').
    attr("fill", "rgba(100,0,0,.3)");

Это именно то, что я хочу, за исключением, что я сделал красные, желтые и зеленые полосы фона фиксированной высоты.

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

Например, на изображении зеленая полоса находится где-то между 300M и 200M. Если вы удалите все данные графика, кроме красных (вертикальных) полос, зеленая полоса (горизонтальная) будет чуть больше 40M. Это связано с тем, что положение / высота фоновых полос не восстанавливаются, тогда как положение / высота данных графика восстанавливается с помощью javascript рикши.

Как я могу поместить эти данные в график рикши, чтобы они были восстановлены?


person bozdoz    schedule 12.11.2012    source источник
comment
по крайней мере, вы должны поместить их в ту же область, где находится график, если я понимаю, что вы правы   -  person zb'    schedule 15.11.2012


Ответы (2)


Решение состоит в том, чтобы настроить функцию обновления для расчета новых высот фоновых полос, чтобы получить отображаемые полосы, вы можете использовать graph.series.active (); вы также можете сохранить вары в той же области ....

так что само решение:

var maxHeight;
var background_update = function(graph) {
    //skip 1st time;
    if (maxHeight === undefined) {return;}
    var series=graph.series.active();
    maxHeight=yScale(get_maximum_all(series));
    //console.log(maxHeight);
    var red_riskpoint=get_maximum("y",series[0]);
    var yellow_riskpoint=get_maximum("y",series[1]);
    var green_riskpoint=get_maximum("y",series[2]);
    //console.log(graph.series.active());
    console.log(yScale(red_riskpoint),yScale(yellow_riskpoint),yScale(green_riskpoint));
    
   // return;
    
    b_red.attr("y", maxHeight - yScale(red_riskpoint)).attr("height", yScale(red_riskpoint));
    b_yellow.attr("y", maxHeight - yScale(yellow_riskpoint)).attr("height", Math.abs(yScale(yellow_riskpoint) - yScale(red_riskpoint)));
    b_green.attr("y", maxHeight - yScale(green_riskpoint)).attr("height", Math.abs(yScale(green_riskpoint) - yScale(yellow_riskpoint)));
    console.log(maxHeight-yScale(green_riskpoint));
};
var get_maximum_all=function(series) {
    var max=0;
    for (var i in series) {
        var stack=series[i].stack;
        for (n in stack) {
            if (stack[n].y>max) {max=stack[n].y;}
            if (stack[n].y0>max) {max=stack[n].y0;}
        }
    }
    return max;
}
    var get_maximum=function(tag,object){
    var max=0;
    for (var i in object.stack) {
        if (object.stack[i][tag]>max) {max=object.stack[i][tag];}
    }
return max;
    }
Rickshaw.Graph.RangeSlider = function(args) {

    var element = this.element = args.element;
    var graph = this.graph = args.graph;


    $(element).slider({

        range: true,
        min: graph.dataDomain()[0],
        max: graph.dataDomain()[1],
        values: [
            graph.dataDomain()[0],
            graph.dataDomain()[1]
            ],
        slide: function(event, ui) {

            graph.window.xMin = ui.values[0];
            graph.window.xMax = ui.values[1];
            graph.update();

            // if we're at an extreme, stick there
            if (graph.dataDomain()[0] == ui.values[0]) {
                graph.window.xMin = undefined;
            }
            if (graph.dataDomain()[1] == ui.values[1]) {
                graph.window.xMax = undefined;
            }
        }
    });


    element.style.width = graph.width + 'px';

    graph.onUpdate(function() {

        var values = $(element).slider('option', 'values');

        $(element).slider('option', 'min', graph.dataDomain()[0]);
        $(element).slider('option', 'max', graph.dataDomain()[1]);

        if (graph.window.xMin == undefined) {
            values[0] = graph.dataDomain()[0];
        }
        if (graph.window.xMax == undefined) {
            values[1] = graph.dataDomain()[1];
        }

        $(element).slider('option', 'values', values);
        background_update(graph);
    });
}

другой код почти такой же, как вы поместили на скрипку,

моя скрипка здесь

обратите внимание, что я не знаю, как рассчитывать точки риска, я просто пытался получить максимальные значения. Я уверен, что вы сможете рассчитать точку риска, просмотрев console.log(series)

b_red, b_green, b_yellow - это d3 выборки инициализированных фоновых полос.

person zb'    schedule 15.11.2012
comment
Вау, это намного больше, чем я ожидал. Я решил, что это просто вопрос правильного размещения кода с переменными, а не жестко запрограммированных значений для высоты стержней. Не могли бы вы объяснить, зачем все это нужно? - person bozdoz; 15.11.2012
comment
я не понимаю, что нужно? Я только что добавил обработчик обновления, который изменяет высоту ваших красных, зеленых и желтых полос и показывает вам способ получения текущих отображаемых данных. Я думаю, вы также можете создать единый график данных с максимальными данными в этой функции обновления - person zb'; 15.11.2012
comment
Привет @eicto. Я нашел ваши функции для получения максимального количества данных и для обработчика onUpdate очень полезными. Я буду награждать вас наградой, если не получу лучшего ответа, а также опубликую свое решение. Один вопрос: вместо получения максимальных данных, как я могу получить максимальную высоту по оси Y? - person bozdoz; 16.11.2012
comment
ты про абсолютный максимум? Я не очень хорошо это проверил, но я думаю, что в плагине Axis есть что-то об этом, так как Axis пересчитан по шкале - person zb'; 16.11.2012

Я нашел какое-то решение с помощью ответа @eicto.

var maxHeight = 250;
var theSVG = d3.select("#chart svg");

//from @eicto: get the maximum value on the current chart
function get_maximum_all(series) { 
    var max=0;
    for (var i in series) {
        var stack=series[i].stack;
        for (n in stack) {
            if (stack[n].y>max) {max=stack[n].y;}
            if (stack[n].y0>max) {max=stack[n].y0;}
        }
    }
    return parseInt(max);
}

//create a function to call on graph update event
function createRiskPoints(riskpoints){
//these variables need to change on each graph update
   var series = graph.series.active();
//this variable should be get_max_y_axis, but I don't know how to do that
   var maxData = get_maximum_all(series);
   var yScale = d3.scale.linear().
  domain([0, maxData]).
  range([0, maxHeight]);

//using dummy values for now
   var riskpoints = (riskpoints) ? riskpoints : [300000000,200000000,100000000];

//insert the bars so they go behind the data values
theSVG.insert("svg:rect", ":first-child").
    attr("x",0).
    attr("y", maxHeight - yScale(riskpoints[0])).
    attr("height", yScale(riskpoints[0]) - yScale(riskpoints[1])).
    attr("width", '100%').
    attr("fill", "rgba(0,100,0,.2)");

theSVG.insert("svg:rect", ":first-child").
    attr("x",0).
    attr("y", maxHeight - yScale(riskpoints[1])).
    attr("height", yScale(riskpoints[1]) - yScale(riskpoints[2])).
    attr("width", '100%').
    attr("fill", "rgba(100,100,0,.2)");

theSVG.insert("svg:rect", ":first-child").
    attr("x",0).
    attr("y", maxHeight - yScale(riskpoints[2])).
    attr("height", yScale(riskpoints[2])).
    attr("width", '100%').
    attr("fill", "rgba(100,0,0,.2)");
}
//call the function
   createRiskPoints();
//call the function on graph update: thanks to @eicto
   graph.onUpdate( createRiskPoints );​

Теперь полосы меняются при изменении графика; однако они не в масштабе. Это будет моей следующей задачей.

http://jsfiddle.net/bozdoz/Q6A3L/

person bozdoz    schedule 15.11.2012
comment
Я понял, что масштабировать нельзя было только потому, что данные, складывающиеся в стопку, увеличивали ось Y до максимальной суммы за каждый год, а не до максимального значения ряда. Я использовал graph.renderer.unstack = true, и он распаковал график, что подходит для моих целей: jsfiddle.net/bozdoz/Q6A3L/11 - person bozdoz; 16.11.2012