简体   繁体   中英

d3js - Add elements based only on nested data

I have some data that looks like this:

[  
   {  
      "territory":"Albania",
      "titles":[
        {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"},
        {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"},
        {"status":"none", "contract date": false, "reversion":false},
        {"status":"active", "contract date": "12/12/2007", "reversion":"12/12/2017"}
      ]
   },
   {  
      "territory":"Argentina",
      "titles":[
        {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"},
        {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"},
        {"status":"none", "contract date": false,  "reversion":false},
        {"status":"active", "contract date": "12/12/2007", "reversion":"12/12/2017"}
      ]
   },
   {  
      "territory":"Bosnia Herzegovina",
      "titles":[
        {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"},
        {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"},
        {"status":"none", "contract date": false,  "reversion":false},
        {"status":"active", "contract date": "12/12/2007", "reversion":"12/12/2017"}
      ]
   }
]

What I want to do is append a circle in d3js for each entry in the nested "titles" array with the "y" position of the circle based on the parent "territory" and the "x" position based on the position in the titles array. I can figure out how to add a circle for the parent array, which I don't want - but I can't figure out how to achieve what I am looking for.

Essentially I want the output to look like this:

界

With each row of circles representing the four titles in a territory.

So far I have code like this:

var width = 940,
    height = 500

var svg = d3.select("#div")
        .append("svg")
          .attr("width", width)
          .attr("height", height)

  var circle = svg.selectAll("circle")
      .data(data)
      .enter().append("circle")
      .attr("r", "12.5")
      .attr("transform", function(d, i) { return "translate(68, " + (((i+1)*28)+64) + ")" });

Which obviously plots one circle for each territory, but I have no idea how to incorporate the titles array into this. I don't really want a circle for each territory, I want a circle for each title. Apologies for how bad my attempt is so far but every time I try to make it more complex it just stops working altogether.

First, you need to create a selection for your level 1 nodes and assign them a container element, let's say g :

var territories = svg.selectAll("g").data(data);
territories
    .enter().append("g");

On this selection, create a new selection with the titles key as data and assign theses selections circle elements :

territories.selectAll("circle")
    .data(function(d) {
        return d.titles;
    })
    .enter().append("circle")
    .attr("r", "12.5")
    .attr('class', function(d, numtitle, numterritory) {
        return 'row_'+numterritory+' col_'+numtitle;
    })
    .attr("transform", function(d, numtitle, numterritory) { 
        var x = 68 + numtitle*30,
            y = 64 + (numterritory+1)*28;
        return "translate(" + x + ", " + y + ")" 
    });

And a demo to play with

 var data = [ { "territory":"Albania", "titles":[ {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"}, {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"}, {"status":"none", "contract date": false, "reversion":false}, {"status":"active", "contract date": "12/12/2007", "reversion":"12/12/2017"} ] }, { "territory":"Argentina", "titles":[ {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"}, {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"}, {"status":"none", "contract date": false, "reversion":false}, {"status":"active", "contract date": "12/12/2007", "reversion":"12/12/2017"} ] }, { "territory":"Bosnia Herzegovina", "titles":[ {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"}, {"status":"reverted", "contract date": "12/12/2007", "reversion":"12/12/2012"}, {"status":"none", "contract date": false, "reversion":false}, {"status":"active", "contract date": "12/12/2007", "reversion":"12/12/2017"} ] } ]; var width = 320, height = 150 var svg = d3.select("#div") .append("svg") .attr("width", width) .attr("height", height) var territories = svg.selectAll("g").data(data); territories .enter().append("g"); territories.selectAll("circle") .data(function(d) { return d.titles; }) .enter().append("circle") .attr("r", "12.5") .attr('class', function(d, numtitle, numterritory) { return 'row_'+numterritory+' col_'+numtitle; }) .attr("transform", function(d, numtitle, numterritory) { var x = 30 + numtitle*30, y = 10 + (numterritory+1)*28; return "translate(" + x + ", " + y + ")" }); 
 .row_0 {fill: red} .row_1 {fill: green} .row_2 {fill: blue} .col_0 {fill-opacity: 1} .col_1 {fill-opacity: 0.75} .col_2 {fill-opacity: 0.5} .col_3 {fill-opacity: 0.25} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id='div'> </div> 

https://jsfiddle.net/nikoshr/4tp1accu/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM