links in d3.js forced directed graph - javascript

In this example, how can I make the text of each node to be a clickable link?
I tried something similar to this code, but the values were not clickable:
var links = text.append("a").attr("xlink:href", "http://www.google.com/");
// A copy of the text with a thick white stroke for legibility.
links.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.attr("class", "shadow")
.text(function(d) { return d.name; });
links.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.text(function(d) { return d.name; });
EDIT / SOLUTION: turns out the css had this attriubte: pointer-events: none;
I had to delete it and then use as Elijah suggested.

Don't use links, drop it and append directly to your text <g> and it should work.
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.attr("class", "shadow")
.text(function(d) { return d.name; })
.on("click", function() {yourFunction(yourVar)})
.on("mouseover", function() {yourFunction2(yourVar)})
.on("mouseout", function() {yourFunction3(yourVar)})
;
Also, if you want to pass the bound data, you'd do that like this:
.on("click", function(d) {yourFunction(d.yourVar)}
Whereas if you want to pass the actual d object, you can do it like this:
.on("click", yourFunction}
In which case yourFunction(d,i) can then reference d.whatever from your bound data.

Related

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

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

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.

D3 change visibilty of nodes on click based on class

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])

Adding label to the links in D3 force directed graph

I have created a force directed graph but I'm unable to add text to the links created.
How can I do so?
Following is my code link
I have used the following line to append the titles on the link's, but its not coming.
link.append("title")
.text(function (d) {
return d.value;
});
What am I doing wrong with this ?
This link contains the solution that you need.
The key point here is that "title" adds tooltip. For label, you must provide slightly more complex (but not overly complicated) code, like this one from the example from the link above:
// Append text to Link edges
var linkText = svgCanvas.selectAll(".gLink")
.data(force.links())
.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("x", function(d) {
if (d.target.x > d.source.x) {
return (d.source.x + (d.target.x - d.source.x)/2); }
else {
return (d.target.x + (d.source.x - d.target.x)/2); }
})
.attr("y", function(d) {
if (d.target.y > d.source.y) {
return (d.source.y + (d.target.y - d.source.y)/2); }
else {
return (d.target.y + (d.source.y - d.target.y)/2); }
})
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("dy", ".35em")
.text(function(d) { return d.linkName; });
The idea of the code is simple: It calculates the midpoint of the link, and displays some text at that place (you can decide what that text actually is). There are some additional calculations and conditions, you can figure it out from the code, however you'll anyway want to change them depending on your needs and aesthetics.
EDIT: Important note here is that "gLink" is the name of the class of links, previously defined with this code:
// Draw lines for Links between Nodes
var link = svgCanvas.selectAll(".gLink")
.data(force.links())
In your example, it may be different, you need to adjust the code.
Here is a guide how to incorporate solution from example above to another example of force layout that doesn't have link labels:
SVG Object Organization and Data Binding
In D3 force-directed layouts, layout must be supplied with array of nodes and links, and force.start() must be called. After that, visual elements may be created as requirements and desing say. In our case, following code initializes SVG "g" element for each link. This "g" element is supposed to contain a line that visually represent link, and the text that corresponds to that link as well.
force
.nodes(graph.nodes)
.links(graph.links)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter()
.append("g")
.attr("class", "link")
.append("line")
.attr("class", "link-line")
.style("stroke-width", function (d) {
return Math.sqrt(d.value);
});
var linkText = svg.selectAll(".link")
.append("text")
.attr("class", "link-label")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) {
return d.value;
});
"g" elements have class "link", lines have class "link-line", ad labels have class "link-label". This is done so that "g" elements may be easily selected, and lines and labels can be styled in CSS file conveninetly via classes "link-line" and "link-label" (though such styling is not used in this example).
Initialization of positions of lines and text is not done here, since they will be updated duting animation anyway.
Force-directed Animation
In order for animation to be visible, "tick" function must contain code that determine position of lines and text:
link.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; });
linkText
.attr("x", function(d) {
return ((d.source.x + d.target.x)/2);
})
.attr("y", function(d) {
return ((d.source.y + d.target.y)/2);
});
Here is the resulting example: plunker

d3: use anchor elements as chart labels

I am getting started with D3 and SVG but I haven't found anything clear on how to add hyperlinks. Here is some code I have to write labels to the left of the bars in a D3 bar chart. Is there a good sample somewhere to convert these labels to hyperlinks (say objects in rangeData had an href and name/label property)? I searched around a bit but haven't gotten much further than the svg spec for adding an anchor element.
chart.selectAll(".bar.barLabel")
.data(rangeData)
.enter().append("text")
.attr("class", "bar")
.attr("x", 0)
.attr("y", function (d, i) { return height(i) + barHeight(y, i) / 2; })
.attr("dx", -20)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function (d) { return d.label; });
You can use the a element to achieve this, very similar to HTML itself. You wrap the content in the a element and provide the link target as the href attribute with xlink namespace.
chart.selectAll("a")
.data(rangeData)
.enter()
.append("a")
.attr("xlink:href", function(d) { return d.href; })
.append("text")
.text(function (d) { return d.label; });
Alternatively, you could use the foreignObject element to directly embed HTML into your SVG.

Categories