如何使用d3.js将图形/数据添加到Rickshaw?

4

这是我所拥有的:

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左右。这是因为背景条的位置/高度没有重新生成,而图表数据的位置/高度则是通过rickshaw javascript重新生成的。我该如何将这些数据放入rickshaw图表中,使其重新生成?

如果我理解正确的话,您至少应该将它们放置在图形所在的相同范围内。 - zb'
2个回答

3
解决方案是设置更新函数来计算背景条的新高度,要显示条形图,您可以使用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);
    });
}

其他代码和你在fiddle中放置的几乎相同,

我的fiddle在这里

请注意,我不确定如何计算风险点,我只是试图获得最大值。我相信您可以通过查看console.log(series)来进行风险点计算

b_red,b_green,b_yellow是已初始化背景条的d3选择。


哇,这比我预期的要多得多。我以为只是将代码放置在变量中而不是硬编码的值来确定条形图高度的问题。你能解释一下为什么需要所有这些吗? - bozdoz
我不明白,需要什么?我只是添加了更新处理程序,它可以更改红色、绿色、黄色条的高度,并向您展示如何获取当前显示的数据。我认为您还可以在该更新函数中制作单个数据图表,其中包含最大数据。 - zb'
嗨@eicto。我发现你的获取最大数据和onUpdate处理程序的函数非常有用。如果没有更好的答案,我将授予你赏金,并发布我的解决方案。不过有一个问题:我该如何获取y轴高度的最大值,而不是获取最大数据? - bozdoz
你的意思是绝对最大值吗?我没有仔细检查过,但我认为Axis插件有相关内容,因为Axis在比例尺上重新计算。 - zb'

1

我在@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/


我意识到它之所以不按比例是因为数据被堆叠了,导致y轴增加到每年的最大总数,而不是系列的最大值。我使用了graph.renderer.unstack = true,它取消了图表的堆叠,这对我的目的来说很好:http://jsfiddle.net/bozdoz/Q6A3L/11/ - bozdoz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接