Trouble with storing enter selections containing t

2019-07-25 03:24发布

问题:

If I try to store the following enter selection, I get an error when I try to access it. I don't have a problem if I remove the transition. Why? Are there other restrictions on storing selections? Here is an example:

// this works
var enterSel = d3.select("svg")
  .selectAll("circle")
  .data([100, 200, 300])
  .enter()
  .append("circle")
    .attr("cx", d => d)
    .attr("cy", "100")
    .attr("fill", "red")
    .attr("r", "0")
    .transition()
    .duration(2000)
    .attr("r", "50");

The above appends and transitions three circles to red, as expected, but the enterSel variable cannot be used for further modifications:

// this doesn't work
enterSel.attr("fill", "green");

Uncaught Error: transition not found       d3.v4.min.js:2 
  at zn (d3.v4.min.js:2)
  at Cn (d3.v4.min.js:2)
  at SVGCircleElement.<anonymous> (d3.v4.min.js:2)
  at qn.each (d3.v4.min.js:2)
  at qn.tween (d3.v4.min.js:2)
  at qn.attrTween (d3.v4.min.js:2)
  at qn.attr (d3.v4.min.js:2)
  at <anonymous>:1:10

I can get around this by doing the transition separately, as follows, but I really want to understand why this is necessary.

// this works
var enterSel = d3.select("svg")
  .selectAll("circle")
  .data([100, 200, 300])
  .enter()
  .append("circle")
    .attr("cx", d => d)
    .attr("cy", "100")
    .attr("fill", "red")
    .attr("r", "0");

enterSel.transition()
    .duration(2000)
    .attr("r", "50");

enterSel.attr("fill", "green");

回答1:

I'll post an answer for the future. A d3 selection returns a selection with the d3.selection.prototype. A transition on the other hand returns a transition with the d3.transition.prototype.

var enterSel = d3.select("svg")
  .selectAll("circle")
  .data([100, 200, 300])
  .enter()
  .append("circle")
    .attr("cx", d => d)
    .attr("cy", "100")
    .attr("fill", "red")
    .attr("r", "0")
    .transition()
    .duration(2000)
    .attr("r", "50");

enterSel.attr("fill", "green");

Does not work because enterSel is now a transition and has different properties than a selection.

var enterSel = d3.select("svg")
  .selectAll("circle")
  .data([100, 200, 300])
  .enter()
  .append("circle")
    .attr("cx", d => d)
    .attr("cy", "100")
    .attr("fill", "red")
    .attr("r", "0");

enterSel.transition()
    .duration(2000)
    .attr("r", "50");

enterSel.attr("fill", "green");

This one works because enterSel is always a selection, which uses the selection prototype. The transition is sectioned away in the second call, but enterSel is always the selection of all the circles.

Hopefully this helps clear things up!