Xnn04
Xnn04

Reputation: 91

D3 append different elements, keep common index

My app is supposed to append different elements to the SVG depending on the data type. My code more or less looks like this:

 var elements = svg.selectAll(".elements")
    .data(someData)
    .enter().append("g");

var circles = elements.filter(function (d,i) {
    return d.type == "category1"
})
    .append("circle")


var rectangles = smallCircles.filter(function (d,i) {
            return d.type == "category2"
        })
            .append("rect")

So, if the data.type = "catgory1", the programme should append a circle, if it is equal to "category2", it should append a rectangle. The problem I'm having is that I'm setting their position on the SVG based on their individual indices ("i" in function(d,i)). However, in order to do so I need the sequence of indices to be consistent among those two element types. Is there a better way to do it than just use a external variable that would ++ everytime a new element gets appended?

Upvotes: 2

Views: 381

Answers (1)

Mark
Mark

Reputation: 108517

Couple ways you could do this.

First, You could use a .each and encapsulate the appending logic:

var elements = svg.selectAll(".elements")
  .data([
    {
      type: "category1"
    },{
      type: "category2"
    } 
  ])
  .enter().append("g");

elements.each(function(d,i){

  // i is index on everything

  var self = d3.select(this);
  switch(d.type) {
      case "category1":
          self.append("circle");
          break;
      case "category2":
          self.append("rect");
          break;
      default:
          break;
  }
});

Or, second, a better way to do this would be to make your elements part of your data:

var data = [
    {
      type: "category1"
    },{
      type: "category2"
    } 
  ];

data.forEach(function(d){
  switch(d.type) {
      case "category1":
          d.elem = "circle"
          break;
      case "category2":
          d.elem = "rect"
          break;
      default:
          break;
  }
});

var svg = d3.select('body').append('svg');

var elements = svg.selectAll(".elements")
  .data(data)
  .enter().append("g");

elements.append(function(d){
  return document.createElement(d.elem);
});

Upvotes: 3

Related Questions