0

I am pretty new to d3.js and maybe my question is very basic, but I haven't been able to find an answer...

I am trying to achieve the following, based on an array of data like this:

var data = [
    {
        "items": 10,
        "selected": 8
    },
    {
        "items": 12,
        "selected": 4
    }];

I would like to create a row of circles for every element of the array. The number of circles should be the equal to the items property and in every row, the circle in selected position should be special (like a different color). For the example above, it should display something similar to:

OOOOOOO*OO

OOO*OOOOOOOO

For the first step, any tips on how to create a variable number of SVG elements based on data values would be a great help.

1 Answer 1

3

Here's an example I made on codepen.

Check out the code below and/or fork the codepen and have a play.

Essentially, what is happening here is that I add a g element for each item in your data array. Normally we might be-able to create a circle for each data element, but since that is contained within a property and variable, I've used an each loop (d3 each). This creates a loop of the number of items, and creates a circle for each. If the element is selected, the fill color changes.

things to note:

  • The g element has a transform of 30 * i on the y axis. This means that each group will stack down the page.
  • In the for loop we get access to the g element using this, but we must use the d3 select function to reference it as a d3 object so we can append.

The code:

//add an svg canvas to the page
var svg = d3.select("body")
.append("svg")
.attr("transform", "translate(" + 20 + "," + 20 + ")"); //this will give it a bottom and left margin

//set up some basic data
var data = [
    {
        "items": 10,
        "selected": 8
    },
    {
        "items": 12,
        "selected": 4
    }];

var groups = svg.selectAll("g")
        .data(data)
        .enter()
    .append("g").attr("transform", function(d, i) {
      return "translate(0," + i * 30 + ")";
    });

groups.each(function(d,i) {
    for (var x = 1; x <= d.items; x++) {
      d3.select(this).append('circle').attr({cx: function(d,i) { return (x + 1) * 22; } ,
             cy: 10 ,
             r: 10 ,
             fill: function(d,i) { return x == d.selected ? "yellow" : "blue" }
       }); 
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, this is exactly what I had in mind. I was trying to apply .each() to create the circles, but to use each I need a selection... for some reason I tried to skip the step to "extract" the data from the array with the for loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.