2016-06-22 3 views
2

Я прочитал учебник Бостока «Nested Selections», но я не мог полностью обернуть свою голову, используя вложенные данные.Вложенные (иерархические) данные с d3

я упростил свою задачу набора данных, как это:

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")... 

Спасибо!

ответ

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 
    }) 
+0

Спасибо '.data (function (d) {return d.modules;})' был трюк для меня. – hobbes3

Смежные вопросы