I am playing around with the drag multiples example, and I noticed something I can't explain.
In this snippet:
var svg = d3.select("body").selectAll("svg")
.data(d3.range(16).map(function() { return {x: width / 2, y: height / 2}; }))
.enter().append("svg")
.attr("width", width)
.attr("height", height);
I changed selectAll
to select
. It still works, but now the svg
elements are added after the </body>
tag. The original code, with selectAll
, adds them after the <body>
tag as you would expect.
Since the original html contains no hardcoded <svg>
element, I would think that both select
and selectAll
just return the empty selection. So I cannot figure out why they result in different behavior.
I'm just looking for an explanation. Thanks!
d3. select selects the first matching element whilst d3. selectAll selects all matching elements. Both functions take a string as its only argument.
selectAll() function in D3. js is used to select all the element that matches the specified selector string. Parameters: This function accepts single parameter HTML tag as a parameter. Return Value: This function returns the selected elements.
D3 provides the ability to set attributes of a selected element using the attr() function. This function takes two parameters: Attribute Name - For example, "r" to set an SVG circle's radius.
Generally in d3 documentation and tutorials, you'll see d used for the current data element and i used for the index of the current data element. The index is passed in as the second element to the function calls like so: function setY(d, i) { return percent_scale(d.
The basic difference between select and selectAll is that select squashes the hierarchy of the existing selections, while selectAll preserves it.
Therefore, when you use one selectAll after the other, the result will be a lot like a list of nested for loops.
http://bost.ocks.org/mike/nest/
Check Mike Bostock's post about select/selectAll: Nested Selections
To quote:
There is an important difference between select and selectAll: select preserves the existing grouping, whereas selectAll creates a new grouping. Calling select thus preserves the data, index and even the parent node of the original selection!
Other answers here are a bit off, and don't cite the correct source; this is only tangentially related to nesting. D3's author explains it in his join concept. I review that here for completeness:
You have two sets (arrays):
These sets may not be exactly the same at any given time during the application's run. So we do a little management to ensure they do match, at all times (every processing frame). Imagine a real-time data set (stream) - maybe last time we only got 98 elements, now instead we've got 100. The page still has 98 <div>
s, but now we need to create 2 more. That's exactly what happens, automagically, in your code:
.selectAll("svg")
you are saying, "Create a set of <svg>
elements even if they don't exist." Another way to put this is, "Let's imagine we can select a set of <svg>
s that matches the dataset we've given. Now, go ahead and create that set.".enter().append(...)
then does. Conversely, if there had been too many elements for our new dataset (because we previously had more in elements in the dataset than we do now), .exit().remove(...)
would deal with that.enter
is the set of elements we need to create; exit
is those we need to remove.
Your .selectAll("svg")
would return nothing, but as it is more of a proposal than an imperative, it then creates what it needs in .enter().append("svg")
, in order to match the dataset given.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With