Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 bar chart selectAll before appending

Tags:

d3.js

charts

I've been learning more about the d3 visualization library, and I've seen a few examples of bar charts that have a snippet that looks like

chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("y", y)
.attr("width", x)
.attr("height", y.rangeBand());

My confusion is with the first selectAll line. What is the purpose of selecting all rects before they exist since we'll be appending new rects on data enter? Does what goes in the selectAll matter if none of those elements exist?

like image 491
Jeff Storey Avatar asked Dec 29 '12 00:12

Jeff Storey


2 Answers

It is part of the declarative nature of the D3 language. The Thinking with Joins article explains it in detail. An excerpt:

But what’s with the selectAll("circle")? Why do you have to select elements that don’t exist in order to create new ones? WAT.

Here’s the deal: instead of telling D3 how to do something, tell D3 what you want. In this case, you want the circle elements to correspond to data: you want one circle per datum. Instead of instructing D3 to create circles, then, tell D3 that the selection "circle" should correspond to data—and describe how to get there. This concept is called the data-join:

This Venn diagram illustrates the data-join. Data bound to existing elements produce the update (inner) selection. Unbound data produce the enter selection (left), and unbound elements produce the exit selection (right). Data Enter Update Elements Exit Thinking with joins reveals the mystery behind the sequence:

The selectAll("circle") returns the empty selection, since the SVG container element (svg) is empty. No magic here.

The empty selection is joined to data: data(data). The data method binds data to elements, producing three virtual selections: enter, update and exit. The enter selection contains placeholders for any missing elements. The update selection contains existing elements, bound to data. Any remaining elements end up in the exit selection for removal.

Since the selection was empty, all data ends up as placeholder nodes in enter().

This is the same append as in the first example, but applied to multiple placeholders; selection methods implicitly iterate over selected elements. The missing elements are added to the SVG container by append("circle").

So that’s it. You wanted the selection "circle" to correspond to data, and you described how to create the missing elements.

like image 172
nautat Avatar answered Dec 31 '22 20:12

nautat


  1. In your example selectAll("rect") is called first. But it returns an empty selection.

  2. data(data) will bind the empty selection with the data. It creates new empty selections.

  3. .enter() identifies any DOM elements that needs to be added when the joined array is longer than the selection.

  4. append("rect") appends a rectangle to each empty selection, which is no longer empty

It is well explained and detailed on this section: D3.js data binding, How it works?

like image 44
Fifi Avatar answered Dec 31 '22 18:12

Fifi