最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Basic d3: why can you select things that don't exist yet? - Stack Overflow

programmeradmin3浏览0评论

I've been learning about d3, and I'm a bit confused about selecting. Consider the following example:

Specifically, let's look at this line:

var node = svg.selectAll(".node")
    .data(nodes)
  .enter().append("circle")
    .attr("class", "node")
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 8)
    .style("fill", function(d, i) { return fill(i & 3); })
    .style("stroke", function(d, i) { return d3.rgb(fill(i & 3)).darker(2); })
    .call(force.drag)
    .on("mousedown", function() { d3.event.stopPropagation(); });

In the documentation it says, "A selection is an array of elements pulled from the current document." I interpret this to mean that svg.selectAll(.node) creates an array of elements of class .node pulled from the current document, but as far as I can tell there are no such elements! Unless I'm confused - and I'm almost certain that I am - the only place in the document where something is given the class "node" is after the selection has already occurred (when we write .attr("class", "node")).

So what is going on here? What does svg.selectAll(".node") actually select?

I've been learning about d3, and I'm a bit confused about selecting. Consider the following example:

http://bl.ocks/mbostock/1021841

Specifically, let's look at this line:

var node = svg.selectAll(".node")
    .data(nodes)
  .enter().append("circle")
    .attr("class", "node")
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 8)
    .style("fill", function(d, i) { return fill(i & 3); })
    .style("stroke", function(d, i) { return d3.rgb(fill(i & 3)).darker(2); })
    .call(force.drag)
    .on("mousedown", function() { d3.event.stopPropagation(); });

In the documentation it says, "A selection is an array of elements pulled from the current document." I interpret this to mean that svg.selectAll(.node) creates an array of elements of class .node pulled from the current document, but as far as I can tell there are no such elements! Unless I'm confused - and I'm almost certain that I am - the only place in the document where something is given the class "node" is after the selection has already occurred (when we write .attr("class", "node")).

So what is going on here? What does svg.selectAll(".node") actually select?

Share Improve this question asked Oct 28, 2015 at 19:51 Paul SiegelPaul Siegel 1,4112 gold badges16 silver badges37 bronze badges 9
  • the .enter().append() after the .data() is the one making the reference for it and then you work on that. – Harshal Carpenter Commented Oct 28, 2015 at 19:53
  • @HarshalCarpenter But what object is .data(nodes).enter().append() acting on? – Paul Siegel Commented Oct 28, 2015 at 19:55
  • .data(nodes) is applied on .selectAll(). Then, if selectAll(rect) does not find any 'rect', then .enter().append() makes the reference and then it works with .data(). – Harshal Carpenter Commented Oct 28, 2015 at 19:57
  • 4 Have a look at Mike Bostocks Thinking with Joins. It answers exactly this question. – altocumulus Commented Oct 28, 2015 at 20:10
  • 1 @HarshalCarpenter There are so many of them. Reading through the tutorials mentioned on the first ten lines will give you a firm grip on the basic concepts and a thorough understanding of what's going on. You may then more easily shift to special techniques like geo data etc. Also have a look at and try to understand the thousands of examples. – altocumulus Commented Oct 28, 2015 at 20:25
 |  Show 4 more ments

1 Answer 1

Reset to default 13

Although, at first sight, this may look like a simple and silly question, the answer to it is probably the most important one for everyone trying to do some serious work with D3.js. Always keep in mind, that D3.js is all about binding data to some DOM structure and providing the means of keeping your data and the document in sync.

Your statement does exactly that:

  1. Select all elements having class node. This may very well return an empty selection, as it is in your case, but it will still be a d3.selection.

  2. Bind data to this selection. Based on the above mentioned selection this will, on a per-element basis, pute a join checking if the new data is a) not yet bound to this selection, b) has been bound before, or c) was bound before but is not included in the new data any more. Depending on the result of this check the selection will be divided into an enter, an update, or an exit selection, respectively.

  3. Because your selection was empty in the first place. All data will end up in the enter selection which is retrieved by calling selection.enter().

  4. You are now able to append your new elements corresponding to the newly bound data by calling selection.append() on the enter selection.

Have a look at the excellent article Thinking with Joins by Mike Bostock for a more in-depth explanation of what is going on.

发布评论

评论列表(0)

  1. 暂无评论