Reputation: 760
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.
Upvotes: 1
Views: 78
Reputation: 33334
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/
Upvotes: 2