Pergunta

Is there a better idiom to append a <svg:g> grouped set of elements to a container on an enter() selection as part of a generic update pattern?

var cell = d3.select(this); // parent container

cell = cell
  .selectAll('.plot').data([0]);   // seems kludgy

cell
  .enter().append('g').classed('plot',true);  // append the wrapping <g> element

cell = cell
  .selectAll("circle")
  .data(_.values(slice));

cell
  .enter().append("circle"); // general enter() -- create plot elements

cell.attr() // etc.  general update--style plot elements

cell
  .exit().remove();

Of course,

if ( cell.select('g.plot').empty() ) {
  cell = cell.append('g').classed('plot', true);
}

instead of the first two statements would do it too, but this seems like a very common operation and the selectAll().data([0]) seems contrived--is there a more elegant d3 idiom?

Foi útil?

Solução

For creating an element if necessary or selecting it otherwise, I would usually use a structure similar to your if block as opposed to using a data join with meaningless data.

Not only is it shorter code, but it means that you're not carrying around that extra data property on your element when it doesn't have any significance. It's also easier for other people to figure out what you're doing!

The only thing I would change is to actually save the selection that you're using for the .empty() test, since if it's not empty you'll be using it. (You could use another variable to save the this-selection, but d3.select(this) isn't exactly a high computation method call to repeat, and even then you'll only be repeating it once, when you first create the group.)

var plot = d3.select(this) // this is the parent container
             .selectAll('g.plot'); //select the plot group if it exists

if ( plot.empty() ) 
    plot = d3.select(this).append('g').classed('plot',true);
           //create the plot group if necessary

var cell = plot.selectAll("circle") //now select/create data elements as usual
  .data(_.values(slice));

cell
  .enter().append("circle"); // general enter() -- create plot elements

cell.attr() // etc.  general update--style plot elements

cell
  .exit().remove();

Outras dicas

Simply append a "g" for every new group of elements that you need.

var cell = d3.select(this)
  .append("g")
    .attr("class","plot")
    .selectAll("circle")
    .data(…);

cell.enter().append("circle")
    .attr(…);

cell.exit().remove();

What doesn't work here?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top