Can't append text to d3.js force layout nodes - javascript

OBJECTIVE: append text to each node in a d3 force layout
BUG: text is appended to the object (I think, see console) but not displayed on screen
Here's the jsfiddle.
node.append("svg:text")
.text(function (d) { return d.name; }) // note that this works for
// storing the name as the id, as seen by selecting that element by
// it's ID in the CSS (see red-stroked node)
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
I'd be so grateful for any thoughts.

You can't add svg text to a svg circle. You should first create an svg g object (g stands for group) for each node, and than add a circle and a text for each g element, like in this code:
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("g");
var circle = node.append("circle")
.attr("class", "node")
.attr("id", function (d) { return d.name; })
.attr("r", 5)
.style("fill", function (d) {
return color(d.group);
});
var label = node.append("svg:text")
.text(function (d) { return d.name; })
.style("text-anchor", "middle")
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
Of course, tick function should be updated accordingly: (also css a little bit)
circle.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
label.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y - 10;
});
Here is jsfiddle.

Related

d3.js forceSimulation() with zoom and drag (I can't add a text label with nodes' info) [duplicate]

This is my code look like, you can also have full code on JsFiddle .
I want to have labels on every node, but I can't.
By the way, labels can be embedded in the circle in the console.
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr("r", 10)
.style("fill", function(d, i){
return colors(i);
})
.call(force.drag);
var label = nodes.append("svg:text")
.text(function (d) { return d.name; })
.style("text-anchor", "middle")
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
force.on("tick", function(){
edges.attr("x1", function(d){ return d.source.x; })
.attr("y1", function(d){ return d.source.y; })
.attr("x2", function(d){ return d.target.x; })
.attr("y2", function(d){ return d.target.y; });
nodes.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; });
label.attr("x", function(d){ return d.x; })
.attr("y", function (d) {return d.y - 10; });
});
Right now, you are appending the text elements to the circle elements, and that simply won't work.
When you write...
var label = nodes.append("svg:text")
You're appending the texts to the nodesselection. However, you have to keep in mind what nodes is:
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
Thus, you are appending the texts to circles, and that doesn't work. They show up when you inspect the page (as <circle><text></text></circle>), but nothing will actually show up in the SVG.
Solution: just change to:
var label = svg.selectAll(null)
.data(dataset.nodes)
.enter()
.append("text")
.text(function (d) { return d.name; })
.style("text-anchor", "middle")
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
Here is the fiddle: https://jsfiddle.net/gerardofurtado/7pvhxfzg/1/

Add text label to d3 node in Force layout

This is my code look like, you can also have full code on JsFiddle .
I want to have labels on every node, but I can't.
By the way, labels can be embedded in the circle in the console.
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr("r", 10)
.style("fill", function(d, i){
return colors(i);
})
.call(force.drag);
var label = nodes.append("svg:text")
.text(function (d) { return d.name; })
.style("text-anchor", "middle")
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
force.on("tick", function(){
edges.attr("x1", function(d){ return d.source.x; })
.attr("y1", function(d){ return d.source.y; })
.attr("x2", function(d){ return d.target.x; })
.attr("y2", function(d){ return d.target.y; });
nodes.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; });
label.attr("x", function(d){ return d.x; })
.attr("y", function (d) {return d.y - 10; });
});
Right now, you are appending the text elements to the circle elements, and that simply won't work.
When you write...
var label = nodes.append("svg:text")
You're appending the texts to the nodesselection. However, you have to keep in mind what nodes is:
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
Thus, you are appending the texts to circles, and that doesn't work. They show up when you inspect the page (as <circle><text></text></circle>), but nothing will actually show up in the SVG.
Solution: just change to:
var label = svg.selectAll(null)
.data(dataset.nodes)
.enter()
.append("text")
.text(function (d) { return d.name; })
.style("text-anchor", "middle")
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
Here is the fiddle: https://jsfiddle.net/gerardofurtado/7pvhxfzg/1/

How to append text in d3 force layout?

I am trying to add text in force layout. First i am creating a svg group and i am appending circle and text into it. The circle is working fine but the text is not working. Here is the code
var node = svg.selectAll("g")
.data(measures.nodes)
.enter().append("g")
.attr("class", "node")
.call(node_drag);
var circle = node.append("circle")
.attr("fill", "blue")
.attr("r",5)
.attr("dx", ".10em")
.attr("dy", ".10em");
var text = node.append("text")
.data(measures.nodes)
.attr("color", "blue")
.text(function(d){ return d.name; })
The text is of the screen because you've missed out the positioning methods. If you add this you'll see text attached to the nodes.
text.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; });

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";
});
});
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/

d3.js: How to add labels to scatter points on graph

I am trying to add labels to the scatter points on this graph: http://bost.ocks.org/mike/d3/workshop/dot-chart.html
I thought that modifying this code a little bit would work, but it didn't:
svg.selectAll(".dot")
.append("text")
.text("fooLabelsOfScatterPoints");
Mike Robinson, your example helped.
For those who are wondering, here is what I did:
I removed:
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.attr("r", 12);
and added:
var node = svg.selectAll("g")
.data(data)
.enter()
.append("g");
node.append("circle")
.attr("class", "dot")
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.attr("r", 12);
node.append("text")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return y(d.y); })
.text("fooLabelsOfScatterPoints");
I appended "text" tags onto "g" tags, as opposed to appending "text" tags onto "circle" tags.
When I tried the node solution, some of my data disappeared (?), so I just added a new class called "dodo" which worked for me:
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.time); })
.attr("cy", function(d) { return y(d.place); })
.style("fill", function(d) { return color(d.species); });
svg.selectAll(".dodo")
.data(data)
.enter().append("text")
.attr("class", "dodo")
.attr("x", function(d) { return x(d.time); })
.attr("y", function(d) { return y(d.place); })
.attr("dx", ".71em")
.attr("dy", ".35em")
.text(function(d) { return d.name;});

Categories