I would like to create a sunburst in d3.js in which some nodes do not follow a strict parent-child relationship.
The relationships my nodes follow is best explained with the below example drawing.
Specifically, the first circle surrounding the root node defines some categories (A, B, C, or D), and each node in all subsequent circles will fall strictly into one of these broad categories. That is, no nodes will cross the grey pencil lines I have drawn. However, on each subsequent concentric circle, it is no longer true that the nodes will fall strictly into their parent nodes. Notice, for example, how the green node with value 0.3, while always strictly a child of category A, is not strictly a child of either the purple or the red node: it crosses the boundaries.
How can I represent this in d3? Here are some potential ideas I have, and I would love advice as to which one makes the most sense.
- Build a sunburst plot without a partition layout (or some other layout), because my data doesn't follow a strict parent-child relationship. Is this possible? My knowledge of d3 is limited, so I have been pretty reliant on tutorials online, and so far, every sunburst plot I've seen uses the partition layout.
- Use a partition layout, and pretend that each concentric circle just consists of the same four nodes (the categories A, B, C, and D), again and again. However, when drawing the outer arcs, draw multiple arcs per node. For example, when drawing circle 2, the purple and red arcs are two different arcs within the same node. When drawing circle 3, the purple, green, and red arcs are three different arcs within the same node.
Option 2 seemed pretty achievable, so I gave it a shot, and added to each node's data point an additional array specifying how to break up the node. So my drawing (omitting B, C, and D) would be represented with the following data:
{
"name": "A1",
"arcs": [1],
"value": 1,
"children": [
{
"name": "A2",
"arcs": [0.4, 0.6],
"value": 1,
"children": [
{
"name": "A3",
"arcs": [0.3, 0.3, 0.4],
"value": 1,
"children": [
{
"name": "A4",
"arcs": [0.2, 0.4, 0.2, 0.2],
"value": 1,
"children": []
}
]
}
]
}
]
}
However, I am struggling to figure out how to draw multiple arcs per node. I currently have the following code which draws one arc for every node, and I am at at a loss for how I would modify it to instead draw multiple arcs, one for each element in the d.arcs
array:
var arcGenerator = d3.svg.arc()
.startAngle(function(d) { return d.x; })
.endAngle(function(d) { return d.x + d.dx; })
.innerRadius(function(d) { return Math.sqrt(d.y); })
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
var path = sunburst_plot.datum(data_root).selectAll("path")
.data(partitionLayout.nodes)
.enter()
.append("path")
.attr("display", function(d) { return d.depth ? null : "none"; }) // hide inner ring
.attr("d", arcGenerator)
.style("stroke", "#fff")
.style("fill", "#000")
.style("fill-rule", "evenodd")
Does anyone have advice as to how to proceed, perhaps either by rethinking my data structure and not using a partition layout, or somehow, below d3's enter()
method, maybe running some sort of loop over each element in the d.arcs
array? I welcome any advice.
Thanks!