ianks
ianks

Reputation: 1768

D3: Attach text to circle such that it has same priority as circle object

I am able to add text to my sketch, but I would like it if I could make my text attached directly to the circle. This means that if a circle gets over-written by another circle, the text will as well. On a higher level not, I am finding the d3 model hard for constructing objects in a way that makes them composable with different shapes, etc. The code seems very procedural to mean so any tips would be greatly appeciated :)

JSFiddle link

      var link = "https://api.github.com/orgs/csci-4830-002-2014/repos"
      d3.json(link, function(error, data) {
        var w = 10000;
        var h = 1000;

        var svg = d3.select("body")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        svg.selectAll("line")
          .data(data)
          .enter()
          .append("line")
          .attr("x1", 5)
          .attr("y1", 5)
          .attr("x2", function (d,i){
              return 30*d.forks_count;
          })
          .attr("y2", function (d,i){
              return 30*d.open_issues_count;
          })
          .attr("stroke-width", 2)
          .attr("stroke", "black");


        svg.selectAll("circle")
          .data(data)
          .enter()
          .append("circle")
            .attr("r", 40)
            .attr("cx", function(d){ return 30*d.forks_count; })
            .attr("cy", function(d){ return 30*d.open_issues_count; })
            .attr("stroke", "black")
            .attr("stroke-width", 2)
            .attr("fill", "white")

        svg.selectAll("text")
          .data(data)
          .enter()
          .append("text")
          .attr("dx", function(d,i){ return 30*d.forks_count; })
          .attr("dy", function(d,i){ return 30*d.open_issues_count; })
          .text(function(d){
            if (d.name.indexOf("challenge") != -1)
              return "C";
            else
              return "H";
          });
      });

Upvotes: 0

Views: 124

Answers (1)

Vinh Tran
Vinh Tran

Reputation: 401

With the way your code written right now, all the lines will be added first, then all the circles, and finally the texts. SVG will always put elements added later on top. So to achieve what you want, you will need to group them up. To do this, you will need to add a g element for each element of your data

var element = svg.selectAll(".element")
    .data(data)
    .enter()
    .append("g")
    .attr("class","element");

Now you can add the line, circle, and text to it

element.append("line")
    .attr("x1", 5)
    .attr("y1", 5)
    .attr("x2", function (d, i) {
        return 30 * d.forks_count;
    })
    .attr("y2", function (d, i) {
        return 30 * d.open_issues_count;
    })
    .attr("stroke-width", 2)
    .attr("stroke", "black");


element.append("circle")
    .attr("r", 30)
    .attr("cx", function (d) {
        return 30 * d.forks_count;
    })
    .attr("cy", function (d) {
        return 30 * d.open_issues_count;
    })
    .attr("stroke", "black")
    .attr("stroke-width", 2)
    .attr("fill", "white")

element
    .append("text")
    .attr("dx", function (d, i) {
        return 30 * d.forks_count;
    })
    .attr("dy", function (d, i) {
        return 30 * d.open_issues_count+6;
    })
   .style("text-anchor", "middle")
    .text(function (d) {
        if (d.name.indexOf("challenge") != -1) return "C";
        else return "H";
    });

You can check the updated JSFiddle at http://jsfiddle.net/9tp1yun7/2/

Upvotes: 2

Related Questions