Juan Juan - 1 month ago 15
Javascript Question

D3.js: Text is not showing inside a circle(They are on the same level of an element-group). How do I bring the text to the front?

The title says it all, this is the codepen. The text is not showing within the circles. How do I do to put the text on the front?. This is the code:

var dataset = [ 5, 10, 15, 20, 25, 40 ];

var w=600,h=600;

var svg=d3.select("body").append("svg")
.attr("width",w)
.attr("height",h);
//1st level:All circles group
var circlesGroup = svg.append("g").classed("general-group",true);
//2nd level: Group of circle and text
var elementGroup= circlesGroup
.selectAll('circle')
.data(dataset)
.enter()
.append("g").classed("element-group",true);

var circle=elementGroup.append('circle');

var circleAttributes= circle
.attr("cx", function(d,i){return i*80+40;})
.attr("cy", h/2)
.attr("r", 20)
.attr("stroke","black")
.attr("fill", "white")
.classed("circle",true);


//text to show
elementGroup.append("text")
.attr("text-anchor", "middle")
.text(function(d) {
return parseInt(d);
}).classed('tweet-number', true);

circle.on('click', function(d,i){

svg.selectAll('circle').transition().duration(500).attr("r", 20);

if(d3.select(this).attr("r")==20){
d3.select(this).transition().duration(500).attr("r", 36);
}else{
d3.select(this).transition().duration(500).attr("r", 20);
}

});

//adding background image
var circlesSelection=svg.selectAll('circle');


This is the generated html which seems to be fine since the circle is at the same level of the text in the element group as it should be:

<svg width="600" height="600">
<g class="general-group">
<g class="element-group">
<circle cx="40" cy="300" r="20" stroke="black" fill="white" class="circle"/>
<text text-anchor="middle" class="tweet-number">5</text>
</g>
<g class="element-group">
<circle cx="120" cy="300" r="36" stroke="black" fill="white" class="circle"/>
<text text-anchor="middle" class="tweet-number">10</text>
</g>
<g class="element-group">
<circle cx="200" cy="300" r="20" stroke="black" fill="white" class="circle"/>
<text text-anchor="middle" class="tweet-number">15</text>
</g>
<g class="element-group">
<circle cx="280" cy="300" r="20" stroke="black" fill="white" class="circle"/>
<text text-anchor="middle" class="tweet-number">20</text>
</g>
<g class="element-group">
<circle cx="360" cy="300" r="20" stroke="black" fill="white" class="circle"/>
<text text-anchor="middle" class="tweet-number">25</text>
</g>
<g class="element-group">
<circle cx="440" cy="300" r="20" stroke="black" fill="white" class="circle"/>
<text text-anchor="middle" class="tweet-number">40</text>
</g>
</g>
</svg>


Thank you very much!

Answer

You forgot to set the x and y positions of the text elements:

//text to show
elementGroup.append("text")
    .attr("text-anchor", "middle")
    .attr("x", function(d,i){return i*80+40;}
    .attr("y", h/2)     
    .text(function(d) {
        return parseInt(d);
     })
    .classed('tweet-number', true);

Here is your CodePen: http://codepen.io/anon/pen/mOyrMM

The <g> element wrap its content and autosize according to the contents, but it doesn't position the contents.

That being said, an alternative is using translate to the groups, and not setting any position for the texts or the circles:

elementGroup.attr("transform", function(d,i){
    return "translate(" + (i*80+40) + "," + h/2 + ")"; 
});

The result is the same, check the CodePen: http://codepen.io/anon/pen/yVyVYy