两个条形图在同一个地方,由一个滑块D3.js控制

时间:2014-06-08 04:35:50

标签: jquery-ui graph d3.js slider

我正在尝试创建一个条形图,当移动独立滑块时,它们会同时更改两个条形图svg高度并且它们是堆叠的,它们是不同的颜色,显示它在同一个图形中显示两个单独的值,基本上显示增长与当前。我正在使用jquery-ui和D3.js.目前它只移动一个svg元素而不是同时移动两个svg元素,Id喜欢它们同时移动。

HTML

<div id="slider" class="slider">
  <label for="amount">Age</label>
  <input type="text" id="amount1" style="border:0;  font-weight:bold;">
</div>

<div id="slider1" class="slider">
   <label for="amount2">Retirement Age</label>
   <input type="text" id="amount2" style="border:0;  font-weight:bold;">
</div>

JS

//initialize sliders

jQuery(document).ready(function($) {

$("#slider").slider({
  max: 100
});
$("#slider").slider({
  min: 18
});
$("#slider1").slider({
  max: 100
});
$("#slider1").slider({
  min: 18
});

//slider actions

$("#slider, #slider1").slider({
  value: 10,
  animate: "fast" ,
  slide: function (event, ui) {

    //capture the value of the specified slider

    var selection = $("#slider").slider("value");
    var selection1 = $("#slider1").slider("value");

    //fill the input box with the slider value

    $( "#amount1" ).val( selection );
    $( "#amount2" ).val( selection1 );

    //set width and height, actually I'm a little confused what this is for

    var w = 200;
    var h = 200;

    //data arrays for svgs
    var dataset = [];
    var dataset1 = [];

    //fill the data arrays with slider values
    dataset.push(selection);
    dataset.push(selection1 + selection);

    //draw rectangle on the page
    var rectangle = svg.selectAll("rect")
    .classed("collapse", true)
    .data(dataset);

**

  

这就是我困惑的地方

**

    //I draw the second rectangle here, however I choose the same svg element,
    //Im not sure what other way to get it to appear in the same space but
    //I am sure this is what is causing my issues
     var rectangle1 = svg.selectAll("rect")
    .classed("collapse", true)
    .data(dataset1);


    //not sure what this does
    rectangle.enter().append("rect");
    rectangle1.enter().append("rect");

    rectangle.attr("width", 200).transition().attr("fill", "#A02222").attr("height", function (d) { console.log('d is ' + d);
    return d;
    }).attr("x", function (d) {
      return 40; //I dont know why I return 40?
    }).attr("y", function (d) {
      return 40;  //Same here dont know why I return 40?
    });

    rectangle1.attr("width", 200).transition().attr("height", function (d) { console.log('d is ' + d);
    return d;
    }).attr("x", function (d) {
      return 40; //I dont know why I return 40?
    }).attr("y", function (d) {
      return 40;  //Same here dont know why I return 40?
    });

  }
// slider actions ends here
});

//Create SVG element
var svg = d3.select(".svgContain").append("svg").attr("width", 125).attr("height", 300);

});

1 个答案:

答案 0 :(得分:2)

对于初学者,您可能需要遵循本教程:http://bl.ocks.org/mbostock/3886208

“回归40;”您想知道的实际上是什么将指定您附加到svg的rect的位置和尺寸。那些不应该只是40,它们应该绑定到数据集中的值,或者基于系列集合中条形系列的索引或者比40更有意义的东西。

有一个堆积条形图数据处理器,它将采用一系列系列并吐出一组新的系列坐标定义,以便更容易计算矩形在svg坐标空间中的堆叠方式:https://github.com/mbostock/d3/wiki/Stack-Layout

然后,更常见的问题是如何处理这些“嵌套”数据集,其中有系列,在系列中有值,您不需要手动跟踪和选择单个系列。有几种方法可以处理这种情况。如果您知道您将只有两个系列,并且您真的希望对每个系列进行细粒度控制,则可以为顶级对象分配一个id,然后通过选择该顶级对象来启动每个绘图的数据连接id ...例如:

var container1 = d3.select("#myContainer1);
container1.selectAll("rect").data(myData1).append("rect");

var container2 = d3.select("#myContainer2);
container2.selectAll("rect").data(myData2).append("rect");

如果你这样做,第一个选择基本上设置后续选择的上下文。因此,只有“#myContainer1”或“#myContainer2”中的rects才会被每个“selectAll”根据您所处的上下文选择。

另一种方法是使用嵌套选择。嵌套的选择有点复杂,但有90%的时间,这是我使用的方法。使用嵌套选择,您可以稍微重构数据,然后应用嵌套的选择/连接将每个系列绑定到dom元素,然后将每个系列的值绑定到每个系列dom元素的子元素。

首先,请阅读:http://bost.ocks.org/mike/nest/

然后尝试使您的数据更像这样:

data = [
    { key: "series1", values: [...]},
    { key: "series2", values: [...]}
];

然后,您将要进行嵌套选择,从选择的“数据”数组开始,并将其绑定到包含两个系列中的每个系列的svg或html元素。

var series = d3.select("svg").selectAll("g.series")
    .data(data, function(d){return d.key; });

series.enter().append("g").attr("class", "series");

此时,d3将为每个系列的svg元素添加一个“g”元素,并将系列对象(包括键和值数组)绑定到附加元素。接下来,您可以进行嵌套选择以将特定于系列的元素添加到g元素...即:

var rect = series.selectAll("rect").data(function(d) { return d.values });
rect.enter().append("rect");

请注意,我们在“.data(...)”调用中使用了一个函数。那是因为我们想要传递给连接的值实际上取决于D3正在处理哪个特定系列。

现在,您已经为每个系列中的每个值添加了一个矩形。由于您使用d3进行数据绑定,并且您在第一个选择中使用了键函数(“.data(data,function(d){return d.key;}”),以后的选择以相同的嵌套/键控方式完成将更新正确的g和rect元素。

这是一个小提琴,它展示了这个概念: http://jsfiddle.net/reblace/bWp8L/2/

一个关键点是你可以更新数据(包括添加额外的系列),整个过程将根据新的嵌套连接正确重绘。