I am beginning with d3.js and I would like to know the simplest way to show a box containing text (a tooltip) when my the mouse is over a node of my force-directed graph. Moreover, the text contained in this box must be custom for each node (something like function(d){return d.fullName;}))
Here is a sample code of what I have for now.
var node = vis.selectAll("g.node")
.data(json.nodes)
.enter().append("svg:g")
.attr("class", "node");
node.append("circle")
.attr("r", 12)
.style("fill", "orange");
Thanks in advance
By box, do you mean a tooltip? In Mike's examples, he uses this idiom:
node.append("title")
.text(function(d) { return d.fullName: });
(With other types of elements (divs only?) you can just use element.setAttribute("title", "title");.)
Related
Still being rather inexperienced in using d3.js I have hit a road block.
Hoping anybody out there can help me.
I am trying to display a picture upon mouse click on a node in a graph.
Ideally, I'd like to click on several nodes and display images. Double click on a node should remove the image. And clicking on the background removes all displayed images. But one step at a time.
What I have done so far is:
Succeeded in using tooltips. I was also able to change the size of a circle node upon mouse clicking on it.
I used as toy project Mike Bostock's force-directed graph example: https://bl.ocks.org/mbostock/4062045 .
I am using d3.js v4
Based on an example on the web I was able to add pictures to all nodes:
Add different images for nodes in d3 v4 network graph
I tried to tailor this example to my needs. First I added:
var defs = svg.append('defs');
Further more:
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter()
.append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); })
.call(node_drag)
.on("click", function(d){
defs.append("pattern")
.attr("x", 0)
.attr("y", 0)
.attr("width", 12)
.attr("height", 12)
.append("image")
.attr("xlink:href", 'https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png')
.attr("width", 12)
.attr("height", 12)
.attr("x", 0)
.attr("y", 0);
})
In my browser the html indicates that the image is added:
But the image is not showing in the browser.
At this point I am turning to you and hope for some hints how I can accomplish displaying an image as node upon clicking with my mouse cursor on it.
Any input is highly appreciated,
Markus
Your inspector is showing that the image was appended to the pattern, but it was never linked to the circle element.
Instead of appending the pattern to the defs inside the click function, you should just append the pattern with a given ID...
var defs = svg.append('defs');
defs.append("pattern")
.attr("x", 0)
.attr("y", 0)
.attr("id", "myPattern")//ID here
.attr("width", 12)
.attr("height", 12)
.append("image")
.attr("xlink:href", 'https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png')
.attr("width", 12)
.attr("height", 12)
.attr("x", 0)
.attr("y", 0);
... and then, inside the click, just change the fill of the circle according to that ID:
.on("click", function() {
d3.select(this).attr("fill", "url(#myPattern)")
})
Here is Bostock's bl.ocks with those changes (I made the circles bigger so you can better see the image): https://bl.ocks.org/anonymous/0e653b6d21c8d57afa234d5d1765efe0/78ba15e533a2b8f8e6575a30d97b27d156ce2faf
I'm building a simple bar chart using d3.js and it works fine.
However, when I try to display texts on each bar, nothing happens. The console doesn't return any error so I can't understand the problem.
My code is available here, I tried to display simple text like "Hello" but still nothing shows up.
Problem:
Appending texts to a rect element in SVG.
Solution:
Append the texts to the SVG or to a group.
Instructions:
You are appending your texts to the rectangles. Nothing will show up as an error in the console because there is no error to show, but the texts won't appear.
You have to create a variable for the texts:
var texts = svg.selectAll(".mytexts")
.data(data)
.enter()
.append("text");
And then setting the attributes:
texts.attr("class", "value")
.attr("x", function(d) { return widthScale(d.vacant); })
.attr("y", heightScale.rangeBand() / 2)
.attr("dx", -3)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) { return format(d.vacant); });
Don't forget to change the CSS accordingly.
I am making a very basic force-directed graph with labels using the d3.js library. Here is part of my code:
var node = d3.select("#canvas").selectAll(".node")
.data(data_nodes)
.enter()
.append("g")
.attr("class","node");
var nodes = node.append("circle")
.style("fill","green")
.style("r",10);
var text = node.append("text")
.attr("dx", 20)
.attr("dy", ".35em")
.style("z-index",1)
.text(function(d){
return d.name;
});
This goes well at the beginning but due to the shifting location of nodes that occurs with the ticking, these text elements that are supposed to serve as labels get covered up by other nodes. I would like to know if there is a way to solve this problem.
I would like to add header to my nodes in d3. But instead of appending it as text I want to append it as image so that in graph scenario all lines will be below header and picture will look cleaner.
Currently because of many links picture looks messy which I want to avoid.
node.append('text')
.attr("class","label")
.attr("style","font-size:12px;")
.html(function(d){
return d.name;
}
})
.attr("x",0)
.attr("y",-radius);
Is there any way how to do this. I read about hidden canvas but not sure exactly how to use here as I am beginner in D3.
Thanks
You can append an image as well.
I've set up a fiddle here, to showcase a working example of appending an image(icon) inside a circle.
node.append("circle")
.attr("cursor","pointer")
.attr("cx", 200)
.attr("cy", 200)
.attr("r", 25)
.style("fill","white")
.style("stroke", "black")
.style("stroke-width", 2);
node.append("image")
.attr("xlink:href", "http://i.stack.imgur.com/bZXWH.png")
.attr("x", 185)
.attr("y", 185)
.attr("width", 32)
.attr("height", 32);
You might also find this tutorial helpful.
In the process of learning D3.js.
Is it possible using a force layout to place a circle within another circle shape as per the picture. I am hoping to transition between a single circle per node to a display showing two circles per node. The size of the effective donut is used to illustrate another variable in the data.
Is this possible?
You don't even need to use anything other than a basic svg circle, as you find in most examples. Just bind the data to it, apply a stroke, and set the stroke-width attr to your other variable. Or r - otherVar, I'm sure you can figure that part out.
If this doesn't satisfy, build your own shape. The 'g' svg element is a container element, and lets you build whatever you like. Add two circles to a g, fill them how you like. Make sure to add them in the right order, since svg has no concept of 'on top', things just get painted in the order that you add them.
edit: okay, quick demo so you can learn some syntax. I didn't add any comments but hopefully the code is very verbose and straightforward. Find it here.
d3/svg is something that you have to just bash your head against for a while. I highly recommend spending some time creating a sandbox environment where you can quickly test new things, save, refresh browser to see results. Minimizing that turnaround time is key.
Thanks to roippi I was able to create a group containing two circle shapes.
var nodeCircles = svg.selectAll("g")
.data(nodes);
// Outer circle
var outer = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius_plus; })
.style("fill", function(d) { return d.color_plus; })
.style("opacity", 0);
// Inner circle
var inner = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius; })
.style("fill", function(d) { return d.color; })
.style("stroke", function(d) { return d3.rgb(d.color).darker(2); })
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.call(force.drag);
Outer circle visibility is toggled via a button.
As mentioned, I use a desktop based IDE to run/test visualisation languages. Currently the IDE supports studies written in D3.js, Raphael, Processin.js, Paper.js and Dygraphs. Picture below...