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; });
Related
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.
I have a bubble chart, where nodes are declared as below and I append for each circle a class which is decided by a array ("category") which decides its category, the variable color is d3.scale.category10() .domain(d3.range(number of elements in "category" array));.
var node = svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("class", function(d) {return category[d.cluster];})
.text(function(d) { return d.text; })
.filter(function(d){ return d.count >= 1; })
.style("fill", function(d) { return color(d.cluster); })
.call(force.drag);
Next, I make a legend which depends on the categories of each of the circles with their color (as shown above). For this, I do the following
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color)
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return category[d]; })
Now, what I want is that when the user clicks the legend text, then the bubbles corresponding to the category of the legend be hidden.
So I add the following to the legend, text object.
.on("click", function(d){
node.selectAll('.'+category[d]).style("visibility", "hidden");
});
But, this does not hide the nodes. Please help.
When you call node.selectAll() it will select all childs of this node that fit the selector. In your case you want to call it on document. So you have to do something like d3.selectAll('.'+category[d])
Iam using d3.js to create a forced graph.
Array nodes and links are filled dynamically. After I'am calling function start()
function start() {
link = link.data(force.links(), function (d) {
return d.source.id + "-" + d.target.id;
});
link.enter().insert("line", ".node").attr("class", "link");
link.exit().remove();
node = node.data(force.nodes(), function (d) { return d.id; });
var nodeEnter = node.enter()
.append("circle")
.attr("r", 8);
nodeEnter.append("text")
.attr("dx", -40)
.attr("dy", 55)
.text(function (d) { return d.id });
node.exit().remove();
force.start();
}
Nodes are OK, links are OK, but the text is not visible!
How can I correctly append the text node in this case?
You're appending a text node to a circle node, which is not valid SVG. Instead you should do something like:
var nodeEnter = node.enter()
.append('g')
.style("transform", "translate(...)")// Here you'll probably want to translate the group)
And then nest both circle and text inside the group:
nodeEnter
.append('circle')
.attr("r", 8);
nodeEnter.append("text")
.attr("dx", -40)
.attr("dy", 55)
.text(function (d) { return d.id });
Thank you for your answer. I tested group element
node = node.data(force.nodes(), function (d) { return d.id; });
var NodeEnter = node.enter()
.append("g");
NodeEnter.append("circle")
.attr("r", 8);
Unfortunately, I see only one circle in the corner of the screen.
Generated svg for 4 nodes is
<svg height="500" width="960">
<line>
...
y1="326.81906005822043" x1="454.86800328354803"
... </line>
<g cy="326.81906005822043" cx="454.86800328354803">
<circle r="8"></circle>
</g>
...
</svg></div>
Also "g" element is in OK position on link(node). Cirle is inside element. Yet I see element in corner in screen
I am new to D3JS, I need to create force layout with both image or circle for each node.
that means, A Image node or Circle node be added dynamically.
Is this possible?, if any examples please answer
Well if you just want to have an image in the middle of the circle try this:
/* Create nodes */
var node = vis.selectAll("g.node")
.data(json.nodes) // get the data how you want
.enter().append("svg:g")
.call(node_drag);
/* append circle to node */
node.append("svg:circle")
.attr("cursor","pointer")
.style("fill","#c6dbef")
.attr("r", "10px"})
/* append image to node */
node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
You can also append a title, some text... See the documentation of selection.append(name) for more info.
For Dynamic Image, you can keep the image in local and using image name you can use the dynamic image from the local.
For making circle, you can use :
var groups = node.enter().append("g")
.attr("class", "node")
.attr("id", function (d) {
return d.entityType;
})
.on('click', click)
groups.append("circle")
.attr("cursor", "pointer")
.style("fill", function(d) { return color(d.entityType); })
.style("fill", "#fff")
.style("stroke-width", "0")
.style("stroke", "#ddd")
.attr("r", 20);
Here, d.entityType will be the name of the image example : favicon.png
groups.append("image")
.attr("xlink:href",function (d) {
return "../assets/images/"+d.entityType+".png";
})
.attr("x", -14)
.attr("y", -15)
.attr("width", 30)
.attr("height", 30)
If you want to add text inside the circle, you can use :
groups.append("text")
.attr("dy", 18)
.style("font-size", "2.5px")
.style("text-anchor", "middle")
.style('fill','#000')
.attr("refX", 15)
.attr("refY", -1.5)
.text(function (d) {
return d.entityName;
});
Following a d3 demonstration (http://goo.gl/lN7Jo), I am trying to create a force-directed graph. I am trying to add a title attribute to my node elements created by doing this.
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
// here is how I try to add a title.
.attr("title", "my title")
.attr("r", 5)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
However, the nodes of my graph are not displaying a title attribute. What is the proper way to do so? Thank you.
In SVG title attributes are really elements that describe their parent, so you would have to follow the example you linked...
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
node.append("title")
.text("my text");
Add this code right below where you initialise your node. This will add some hard-code text as title to each node.
node.append("title")
.text("my text");
If you want to add name as title, do this;
node.append("title")
.text(function (d) {
return d.name;
})