Why aren't my text labels appearing? - d3.js

I'm trying to figure out why my text labels aren't showing up. I don't see any sort of error in the console, just ... no labels.
svg.selectAll("text")
.data(data)
.enter().append("text")
.text(function(d) {
return (d.money);
})
.attr("text-anchor", "middle")
.attr("x", function(d) { return x(d.year); })
.attr("y", function(d) { return y(d.money); })
.attr("class", "axis");
The full example is at https://jsfiddle.net/s3jo8gkL/5/

Right now, you are selecting all the text elements, and you already have texts in your SVG. Just change your first line, selecting any given class (or any given ID, any fake element or even any SVG element that doesn't exist at that point):
svg.selectAll(".thistext")
.data(data)
.enter().append("text")
.text(function(d) {
return (d.money);
})
.attr("text-anchor", "middle")
.attr("x", function(d) { return x(d.year); })
.attr("y", function(d) { return y(d.money); })
.attr("class", "axis");

Related

Adding labels to groups in d3 force layout

Is there a way to add labels to the groups for the d3-cola force layout example here
I have added tooltips:
var group = svg.selectAll(".group")
.data(groups)
.enter().append("rect")
.classed("group", true)
.attr("rx",20)
.attr("ry",20)
.style("fill", function (d) { return color(d.id); })
.call(cola.drag);
group.append("title")
.text(function (d) { return d.id; });
I tried adding this part:
var groupText = svg.selectAll(".group")
.append("text")
.attr("class", "link-label")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 9px Arial")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) {
return (d.id);
});
And then in the tick function:
groupText
.attr("x", function(d) {
return ((d.bounds.x + d.bounds.width())/2);
})
.attr("y", function(d) {
return ((d.bounds.y + d.bounds.height())/2);
});
But it doesn't show up.

Labels do not display with D3 v4 bar chart

I am struggling to add vertical labels to the individual bars in a D3 Version 4 chart. I think the problem is that the <text> element cannot be within the <rect> element according to SVG standards but for the life of me, I cannot work out how to have the <text> element appear just outside the <rect> element. Problematic code is here:
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y(d.Country); })
.attr("x", function(d) { return x(d.freqStart); })
.attr("width", function(d) { return x(d.freqEnd) - x(d.freqStart); })
.attr("height", y.bandwidth())
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.text(function(d) { return d.Operator; });
The full code can be found at
https://plnkr.co/edit/JiuYKhRxgqtG1osYjJHq?p=preview
Yes, you are right. <text> elements cannot be inside <rect> elements. Technically, you can append them but you wont see anything.
That being said, the common way to do this is to append your rects to a <g> element. This way, you can add text labels to the corresponding group accordingly.
This is the portion of your code that I changed. For each bar, we append a new <g> element. In the second part of the code, we add the text labels to the same g elements.
g.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bars")
.append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y(d.Country); })
.attr("x", function(d) { return x(d.freqStart); })
.attr("width", function(d) { return x(d.freqEnd) - x(d.freqStart); })
.attr("height", y.bandwidth());
var bars = svg.selectAll(".bars");
bars.append("text")
.attr("class", "label")
.attr('transform', 'rotate(-90)')
.attr("y", function(d) { return x(d.freqStart) + 20; })
.attr("x", function(d) { return -y(d.Country) + 5; })
.text(function(d) { return d.Operator; });
Full working code here - https://plnkr.co/edit/9rUZXl7mfw32sWJih2Ob?p=preview

How to add a background color to d3 text elements?

I'm trying to add a rect element behind text with d3 to simulate background-color which doesn't exist for d3 text elements. I would like the rect to have the exact same size as the text itself.
node.append("text")
.attr("class", "text")
.attr("text-anchor", "middle")
.attr("dx", 0)
.attr("dy", ".35em")
.text(function(d) {
var bbox = this.getBBox();
node.insert("rect",":first-child")
.attr("x", bbox.x)
.attr("y", bbox.y)
.attr("width", bbox.width)
.attr("height", bbox.height)
.style("fill", "yellow");
return d.name;
});
this.getBBox() returns 0 for both x and y.
The following code display the box, but it size doesn't very with text size, and the box is drawn even when text is not (when an image exists).
node.filter(function(d) {return (!d.image)}).append("text")
.attr("class", function(d) { return "text "+d.type; })
.attr("text-anchor", "middle")
.attr("dx", 0)
.attr("dy", ".35em")
//.text(function(d) { if (!d.imgB64) { return d.label; }
.text(function(d) {
return d.name;
})
.each(function(d) {
var bbox = this.getBBox();
node.insert("rect", "text")
.style("fill", "#FFE6F0")
.attr("x", bbox.x)
.attr("y", bbox.y)
.attr("width", bbox.width)
.attr("height", bbox.height);
});
SOLUTION
Thanks to Cool Blue, the following code now properly works: display a rect behind the text so that it is readable when larger than the node circle. In the futur it could be improved with a sphere arc rather than the rect to only hide the circle frame behind the text...
// only display node labels if node has no image
node.filter(function(d) {return (!d.image)}).append("text")
.attr("class", function(d) { return "text "+d.type; })
.attr("text-anchor", "middle")
.attr("dx", 0)
.attr("dy", ".35em")
.text(function(d) {
return d.name;
})
.call(getTextBox);
// only display a rect behind labels if node has no image
node.filter(function(d) {return (!d.image)}).insert("rect","text")
.attr("x", function(d){return d.bbox.x})
.attr("y", function(d){return d.bbox.y})
.attr("width", function(d){return d.bbox.width})
.attr("height", function(d){return d.bbox.height})
.style("fill", "#FFE6F0");
function getTextBox(selection) {
selection.each(function(d) { d.bbox = this.getBBox(); })
}
As mentioned in the comments, use this pattern and add whatever details you need...
var textNode = node.filter(function(d) {return (!d.image)})
textNode.append("text")
.attr("class", "text")
.attr("text-anchor", "middle")
.attr("dx", 0)
.attr("dy", ".35em")
.text(function(d) {
return d.name;
}).call(getBB);
textNode.insert("rect","text")
.attr("width", function(d){return d.bbox.width})
.attr("height", function(d){return d.bbox.height})
.style("fill", "yellow");
function getBB(selection) {
selection.each(function(d){d.bbox = this.getBBox();})
}

Problem to show dynamic text on mouseover in D3.js and json file?

I am brand new to the d3 and I try to display a text included in a json file on circle in d3.
svg.selectAll("circle")
.data( theData ).enter()
.append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", theCircleRadius);
svg.selectAll("text.server")
.data( theData ).enter()
.append("text")
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.style("text-anchor", "middle");

D3.. trying to add labels to a bar chart, adds all values to each label

I'm relatively new to D3 and trying to add labels to a bar chart.. I keep running into the problem of labels applying all values to each label. Precedding this code is normal data load etc.
// Controls Bar Layout and Offset (x(d.weekOf)+20)
var property = svg.selectAll(".property")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + (x(d.weekOf)+20) + ",0)"; });
// Theese are the bars, width is the width of the bars
property.selectAll("rect")
.data(function(d) { return d.emissions; })
.enter().append("rect")
.attr("width", "80")
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.attr("opacity", "0.7")
.style("fill", function(d) { return color(d.name); });
// Add Capacity Labels
property.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d, i) {return d.Internal; })
.attr("x", 41)
.attr("y", 210)
.attr("text-anchor", "middle");
Clearly I'm missing something simple..?
Your labels are a subselection of the property selection, so instead of using data() to join each property label to the entire dataset as you are, you should instead use data to join to the corresponding parent datum, like so:
property.selectAll("text")
.data(function(d) {return [d];})
.enter()
.append("text")
.text(function(d, i) {return d.Internal; })
.attr("x", 41)
.attr("y", 210)
.attr("text-anchor", "middle");

Resources