D3 adding labels to forced graph nodes - d3.js

I am trying to use the code at http://bl.ocks.org/GerHobbelt/3071239. Additional thing I need with this is to have labels with each node. I am trying like :
node.enter().append("circle")
.attr("class", function(d) { return "node" + (d.size?"":" leaf"); })
.attr("r", function(d) { return d.size ? d.size + dr : dr+1; })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.style("fill", function(d) { return fill(d.group); })
.on("click", function(d) {
console.log("node click", d, arguments, this, expand[d.group]);
expand[d.group] = !expand[d.group];
init();
})
node.append("text")
.attr("dy", ".3em").text("Node Name To Display")
But this does not work.
Can someone please help?

Related

How to fit text inside nodes at bottom in pack layout in d3?

I created d3 pack layout.Text is added in nodes. Requirement is text should be fit in circular nodes in such way that Text should be at bottom, proportional to node size and should be fit inside node.but text is either overlapping or hides behind another node or not proportional to nodes as in JSFiddle examples
http://jsfiddle.net/oo66o0q0/11/,
http://jsfiddle.net/oo66o0q0/12/,
http://jsfiddle.net/oo66o0q0/13/
.So how to resolve all issue with one code?
function treeLayout(nodes){
var node = diagramLayout.selectAll(".node");
node = node.data(nodes.descendants(), function(d) {
return d.uid;
});
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("height", nodeHeight)
.attr("width", nodeWidth)
nodeEnter.append("circle")
.attr("id", function(d) { return "node-" + d.data.name; })
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.depth); });
nodeEnter.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
var nodeText = nodeEnter.append("text")
.text(function(d) { return d.data.name; })
.attr("clip-path", function(d) { return "url(#clip-" + d.data.name + ")"; })
.style("text-anchor", "middle")
.style("stroke", "#000")
.style("stroke-width", "0.1px")
.attr("y", function(d) {
return d.r-(d.r/d.data.name.length);
})
.style("font-family", "sans-serif")
.style("font-size", function(d) {
return d.r/(d.data.name.length)+ "px";
})
}
}

Displaying text labels correctly

I'm trying to show a label on each circle of the svg and change them every time the select box changes. Something shows up, but it's unreadable and I don't know what's wrong.
Here's the js bin: http://jsbin.com/legexovicu/edit?html,output
And this is the relevant code:
var pathContainers = svg.selectAll('g.line')
.data(operacion);
pathContainers.enter().append('g')
.attr('class', 'line')
.attr("style", function(d) {
return "stroke: " + color_hash[operacion.indexOf(d)][1];
});
pathContainers.selectAll('path')
.data(function (d) { return [d]; }) // continues the data from the pathContainer
.enter().append('path')
.attr('d', d3.svg.line()
.x(function (d) { return xScale(d.x); })
.y(function (d) { return yScale(d.y); })
);
pathContainers.selectAll('text')
.data(function (d) { return d; })
.enter().append('text')
.attr('x', function (d) { return xScale(d.x) + 20; })
.attr('y', function (d) { return yScale(d.y) + 25; })
.text( function (d) { return d.name; })
.attr("text-anchor", "middle")
.attr("font-family", "arial")
.attr("font-size", "5px")
.attr("fill", "white")
.attr('background','white');
// add circles
pathContainers.selectAll('circle')
.data(function (d) { return d; })
.enter().append('circle')
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function (d) { return yScale(d.y); })
.attr('r', 2)
.style('fill', 'white')
.attr("title", function(d) { return d.name });
If I look the generated html, I see something like this:
<text x="70" y="75" text-anchor="middle" font-family="arial" font-size="5px" fill="white" background="white">Consti</text>
But I end up getting something illegible.
Add this to your texts:
.style("stroke-width", 1);
Here is your JSBin: http://jsbin.com/lujuhupata/1/edit?html,output

Different shape/image for leaf nodes in pack layout

I am using a pack layout in d3.js (https://github.com/mbostock/d3/wiki/Pack-Layout) and load in a json file with a parent-child structure.
My question is probably a very trivial one: I would like to append a circle or an image(or maybe a rectangle) depending on whether d.children returns parent or child (where child in basically a leaf node).
This is a bit of the code that appends circles to all nodes:
vis.selectAll("circle")
.data(nodes)
.enter().append("svg:circle")
.attr("class", function(d) { return d.children ? "parent" : "child"; })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.r; });
Does anyone have any suggestions?
Thank you,
Use a filter function:
// if you have children, append a circle
node.filter(function(d){
return d.children;
})
.append("circle")
.attr("r", function(d) { return d.r; });
// if you don't have children, append a rect
node.filter(function(d){
return !d.children;
})
.append("rect")
.attr("width", function(d) { return d.r; })
.attr("height", function(d) { return d.r; })
.attr("x", function(d) { return -d.r/2; })
.attr("y", function(d) { return -d.r/2; });
Example here.

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

Why is my update function creating an entirely new force-directed graph?

I'm looking at this other question and this example provided in that question, and I cannot quite get my own update function to work:
update = function() {
path = svg.append("svg:g").selectAll("path")
.data(force.links());
path.enter().append("svg:path")
.attr("class", "link")
.attr("fill", "none")
.attr("stroke", "#666")
.attr("stroke-width",
function(d) {
return (Math.floor(Math.log(d.value - min_val) / Math.log(2)) + 1) + "px"
})
.attr("marker-end", "url(#generic_arrow_marker)")
.on("mouseover",
function(d, i) {
if(d3.select(this).attr("stroke") != "#666") {
mousedOut = false;
}
})
.on("mouseout",
function(d, i) {
if(d3.select(this).attr("stroke") != "#666") {
mousedOut = true;
restoreGraph();
}
});
path.exit().remove();
circle = svg.append("svg:g").selectAll("circle")
.data(force.nodes());
circle.enter().append("svg:circle")
.attr("r",
function(d) {
return (20 + Math.floor(Math.log(d.pagerank) / Math.log(2)) * 2) + "px"
})
.attr("fill", "#ccc")
.attr("stroke", "#333")
.attr("stroke-width", "1.5px")
.on("mouseover", // select relevant data nodes on click
function(d, i) {
mousedOut = false;
d3.select(this).attr("class", "selected");
transitions(d);
$("span#user").text(d.name)
$("span#pagerank").text(d.pagerank)
})
.on("click",
function(d, i) {
incoming = !incoming;
transitions(d);
})
.on("mouseout",
function(d, i) {
mousedOut = true;
d3.select(this).attr("class", "");
restoreGraph();
})
.call(force.drag);
circle.exit().remove();
text = svg.append("svg:g").selectAll("g")
.data(force.nodes());
textEnter = text.enter().append("svg:g");
textEnter.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.attr("class", "shadow")
.text(function(d) { return d.name; })
textEnter.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.text(function(d) { return d.name; })
text.exit().remove();
force.start();
}
Whenever I call update(), it creates an entirely new copy of the existing D3 graph, even if I didn't change anything.
Ideas on what I might be doing wrong?
I figured it out as soon as I posted the question...
It was because I had svg.append("svg:g") for path, circle, and text.
I think I'll leave this question up in case it helps anyone else...

Resources