bambooom bambooom - 1 year ago 68
CSS Question

d3.js : attribute setting not working after binding data and entering elements

I'm learning

from the very beginning. However, in the Entering Element section of the tutorial I'm reading, I cannot get the result as the same as in the article.

.data([32, 57, 112, 293])
.attr("cy", 60)
.attr("cx", function(d, i) { return i * 100 + 30; })
.attr("r", function(d) { return Math.sqrt(d); });

After binding the data, entering the element and appending one more
, the attributes setting only applied on the appended
, not all the circles.

I hereby attached the codepen.

Is this behaviour normal or do I misunderstand something?

Answer Source

Yes, this is the normal behaviour. Here is your problem: you already have 3 circles in the SVG. So, when you bind the data, your "enter" selection has just one circle (the fourth one), and all the attributes are being set only for this last circle.

The enter/update/exit selections are based on the relationship between data and elements. When you bind your data (the 4 numbers in the array), you already have 3 elements in the SVG. Thus, you have:

  • Enter selection: data not corresponding to any element. In your case, 1 circle.

  • Update selection: data corresponding to an element. In your case, 3 circles.

  • Exit selection: element not corresponding to any data. In your case, zero circles.

To redraw all the 4 circles (3 previous and one new), you have to do something like this:

var svg ="svg");

var myCircles = svg.selectAll('circle')
    .data([32, 57, 112, 293]);//binds the data

myCircles.enter().append("circle");//enter selection

myCircles.attr("cy", 60)
    .attr("cx", function (d, i) {
      return i * 100 + 30;
    .attr("r", function(d) {
      return Math.sqrt(d);
    });//updates all circles

Doing this way, you set the attributes both for the "enter" and the "update" selections. Here is your updated Pen (I put a setTimeout of 1 second, just for you to see the original 3 circles before the change):

Please note that I'm not comparing your code with Bostock's tutorial, or saying what you did "wrong". I'm simply explaining why your code doesn't update the 4 circles.