d3

时间:2016-06-22 18:00:17

标签: d3.js nested hierarchical-data

我读过Bostock的“Nested Selections”教程,但我无法完全使用嵌套数据。

我已将问题简化为这样的数据集:

var data = [{
  "id": "foo",
  "row": 0,
  "col": 0,
  "row_size": 200,
  "col_size": 100,
  "modules": [{
    "id": "foo1",
    "row": 0,
    "col": 0
  }, {
    "id": "foo2",
    "row": 1,
    "col": 0
  }]
}, {
  "id": "bar",
  "row": 0,
  "col": 1,
  "row_size": 200,
  "col_size": 100,
  "modules": [{
    "id": "bar1",
    "row": 0,
    "col": 1
  }, {
    "id": "bar2",
    "row": 1,
    "col": 1
  }]
}]

我正试图像这样动态创建svg

<svg width="500" height="500">
  <g transform="translate(20,20)">
    <g transform="translate(0,0)" class="outside_box">
      <rect x="0" y="0" width="100" height="200" fill="white" stroke="red" stroke-width="10"></rect>
      <text x="50" y="100" text-anchor="middle" alignment-baseline="central" font-size="50">foo</text>
      <g class="inside_box">
        <g transform="translate(0,0)">
          <rect x="0" y="0" width="100" height="100" fill-opacity="0.5" stroke="blue"></rect>
          <text x="50" y="50" text-anchor="middle" alignment-baseline="central">foo1</text>
        </g>
        <g transform="translate(0,100)">
          <rect x="0" y="0" width="100" height="100" fill-opacity="0.5" stroke="blue"></rect>
          <text x="50" y="50" text-anchor="middle" alignment-baseline="central">foo2</text>
        </g>
      </g>
    </g>
    <g transform="translate(100,0)" class="outside_box">
      <rect x="0" y="0" width="100" height="200" fill="white" stroke="red" stroke-width="10"></rect>
      <text x="50" y="100" text-anchor="middle" alignment-baseline="central" font-size="50">bar</text>
      <g class="inside_box">
        <g transform="translate(0,0)">
          <rect x="0" y="0" width="100" height="100" fill-opacity="0.5" stroke="blue"></rect>
          <text x="50" y="50" text-anchor="middle" alignment-baseline="central">bar1</text>
        </g>
        <g transform="translate(0,100)">
          <rect x="0" y="0" width="100" height="100" fill-opacity="0.5" stroke="blue"></rect>
          <text x="50" y="50" text-anchor="middle" alignment-baseline="central">bar2</text>
        </g>
      </g>
    </g>
  </g>
</svg>

我的示例中的定位,大小调整和颜色无关紧要(我只是添加了额外的属性以使SVG清晰易懂);但<g><text><rect>的分组非常重要。我还想从头开始创建SVG(空白画布),所以尝试做类似

的事情
d3.selectAll("g").data(data).enter().append("g")...

谢谢!

1 个答案:

答案 0 :(得分:2)

这应该这样做。我还没有对它进行过测试,因此可能会出现错误,但总体结构是您所追求的。

var svg = d3.select("body").append("svg") // here you'll also want to apply width and height .attr's
var mainG = svg.append("g") // this you'll also want to translate(20,20) as your mockup suggests

// Now bind the outer level, to produce a 2-element selection bound to 'data'
var gOuter = mainG.selectAll("g.outside_box").data(data)
var gOuterEnter = gOuter.enter().append("g")
    .attr("class", "outside_box")
    // also to this you can apply translation as you wish

gOuterEnter.append("rect") // and set the rect's attributes as needed
gOuterEnter.append("text") // and set the text's attributes and text as needed
gOuterEnter.append("g")
  .attr("class", "inside_box")

// Now comes the work with the nested data:
var gModules = gOuterEnter.select(".inside_box").selectAll("g").data(function(d) {
  // here d is the outer datum, and lets you access
  // its nested 'modules' array, which is what you want
  // to return, as instructed by Bostocks "Nested Selections" tutorial
  return d.modules
})

var gModulesEnter = gModules.enter()
  .append("g")

gModulesEnter.append("rect") // and set attributes
gModulesEnter.append("text")
  .text(function(m) {
    // here m is each module's datum, so you can return its id
    // to set the text to what you want
    return d.id
  })