Reputation: 3
I am new to d3 and still working out some of the basics.
From what I understand you shouldn't need for loops with d3.
If I have the following data:
[
{
"title": "mine",
"shapes" : {
"circle" : 15,
"square": 20
}
},
{
"title": "yours",
"shapes": {
"circle": 2,
"square": 18
}
}
]
how do I append 15 circles and 20 squares?
I know how to append an element for each item in an object, but not how to use an integer in object.
Any guidance would be greatly appreciated!
Upvotes: 0
Views: 944
Reputation: 22443
The point of the d3 data pipeline is to avoid unnecessary explicit looping and procedural code. Looping still has a place.
But let's say you want to be idiomatic, and not loop. Then when you need is d3.range()
. It turns an integer bound into a list. E.g. d3.range(4) == [0, 1, 2, 3]
. If you're going through a pipeline, have an integer, and need elements for every value up to that integer, the key snippet is:
g.selectAll('circle')
.data(d => d3.range(d.shapes.circle))
.enter()
.append('circle')
which converts the number of circles coming in from your data item to that many circles. Unfortunately, it's not quite that simple in practice. You're processing a multi-level structure, and you probably want to not just produce N different circles, but vary those circles based on some higher-level context. So in practice it's more like:
g.selectAll('circle')
.data((d, i) => d3.range(d.shapes.circle)
.map(j => [i, j]))
.enter()
.append('circle')
That is, for the i'th record in your data array, the data fed to create circles combines i with the values of j coming from d3.range()
.
The full code's a bit longer than fits comfortably here, but here's a live example on Plunker.
Colors are chosen by the order in the input data; shape positioning and opacity are chosen randomly.
Upvotes: 1