Unable to add text on link in d3 collapsible tree - d3.js

in the above code my .append("text") dosent work.I do not get any text inserted on my links.
i tried using link.append("path")..using this i can see the text but not the links. I want to use
link.insert("path") and still be able to add text and be able to collapse and expand nodes along with the link
text. Pls help
var link = svg.selectAll("path.link")
.data(links, function (d) { return d.target.id; });
// Enter any new links at the parent's previous position.
// var link1=link.enter();
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function (d) {
var o = { x: source.x0, y: source.y0 };
return diagonal({ source: o, target: o });
});
link.enter()
.append("g")
.attr("class", "link")
.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("transform", function(d) {
return "translate(" +
((d.source.y + d.target.y)/2) + "," +
((d.source.x + d.target.x)/2) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) {
console.log(d.target.name);
return d.target.name;
});

This was difficult to answer without a fiddle or a link to working code, but I think this is maybe what you were after: http://jsfiddle.net/henbox/82pepd2a/9/
You should see red text on the links that corresponds to the node text (in black) and these should transition as nodes \ links move.
I created a new variable var linktext to handle the text separate from the links (path elements) themselves, since this was what was causing you paths not to show.
I also used insert("g") instead of append("g") to add a completely new g element, rather than placing the g and text inside each path. Here's the important stuff:
// Update the link text
var linktext = svg.selectAll("g.link")
.data(links, function (d) {
return d.target.id;
});
linktext.enter()
.insert("g")
.attr("class", "link")
.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function (d) {
//console.log(d.target.name);
return d.target.name;
});
Finally I added 'update' and 'remove' blocks for linktext using a similar approach used for links. Note that I also moved the styling to CSS for tidyness

Related

d3.js sankey link color

I am looking for making the link color same as node fill color in d3 sankey charts.
I am using following function to get the node color
function getNodeColor(d){
console.log(d3.rgb(d.color).darker(2));
return d3.rgb(d.color).darker(2);
}
Following is my code for painting the text color of the links
// add in the title for the nodes
node.append("text")
.attr("x", -6)
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function(d) { return d.name; })
.filter(function(d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start")
.style("stroke", getNodeColor);
Above works perfectly fine and the text displays the node text with the node color.
Same is not true when I try to change the stroke value in link definition by same way :
var link = svg.append("g").selectAll(".link")
.data(graph.links)
.enter().append("path")
.attr("class", "link")
.attr("d", path)
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
.style("stroke", getNodeColor)
.sort(function(a, b) { return b.dy - a.dy; });
I am new to d3 sankey and follow http://bl.ocks.org/d3noob/c9b90689c1438f57d649
Help appreciated...
Bottomline : I am looking for making the link/chord colors of sankey chart same as that of rect fill color...
You can use the following code to use the source node color for the links in your graph. You could also use target.color if you prefer to use the target node color.
svg.selectAll(".link")
.style('stroke', function(d){
return d.source.color;
})
This code would need to be placed after the code which sets the node colors.

LinkText is not working in tree layout d3js

I am trying to put linkText for the link in tree layout d3js but it is not wlrking, created the jsfiddle project here. Can anybody let me know, why the linkText is not coming.
var link = svg.selectAll(".link")
.data(links, function (d) {
return d.target.id;
});
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function (d) {
var o = {
x : source.x0,
y : source.y0
};
return diagonal({
source : o,
target : o
});
});
link.transition().duration(duration)
.style("stroke", function (d) {
return "#99FFCC";
})
.attr("d", diagonal);
link.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 12px Arial").attr("transform", function(d) {
return "translate(" +
(d.target.y - 50) + "," +
(d.target.x - 10) + ")";
}).attr("text-anchor", "middle").text(function (d) {
alert(d.target.label);
return d.target.label;
});
Your mistake is in here:
link.enter().insert("path", "g")
.attr("class", "link")
...
...
link.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
This code will put the text within the path DOM, which is incorrect.
Text DOM should never be within the path DOM.
Correct code should have been this:
// Update the links…
var link = svg.selectAll("path.link")
.data(links);
//adding the text to the svg
link.enter().insert("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("transform", function (d) {
return "translate(" + (d.target.y - 30) + "," + (d.target.x - 10) + ")";
})
.attr("text-anchor", "middle")
.text(function (d) {
console.log(d.target.label);
return d.target.label;
});
Full working code here.

Adding/Removing labels of line points with update

I'm using a range slider to add/remove points from a line which follows an histogram.
Without updating the data, the text labels are shown correctly, when I update the values with the slider I'd like that the text-labels follow the line, so they show the values of the points correctly.
The update for the line works, but I am not able to update the text labels correctly.
Right now the laberls are plotted like so outside of the on-change function:
var SerifText = svg.append("g")
.attr("id", "serif-labels")
.selectAll("text")
.data(histogSerif)
.enter()
.append("text")
.text(function (d) { return d.y >= 1 ? d.y : null; })
.attr("text-anchor", "middle")
.attr("font-size", 10 + "px")
.attr("fill", "#f0027f")
.attr("x", function (d) { return x(d.x)})
.attr("y", function (d) { return y(d.y) - padding; })
.attr("visibility", "hidden"); //the hidden & visible is managed by an external checkbox
And then on the on-change function I put this code:
SerifText.selectAll("text").remove();
/* If I do SerifText.remove() it does remove the text but also the group of course,
but as it is it doesn't work */
SerifText.selectAll("text")
.data(histogSerif)
.enter()
.append("text")
.text(function (d) { return d.y >= 1 ? d.y : null; })
.attr("text-anchor", "middle")
.attr("font-size", 10 + "px")
.attr("fill", "#f0027f")
.attr("x", function (d) { return x(d.x)})
.attr("y", function (d) { return y(d.y) - padding; });
But this doesn't work unfortunately. I'd like also to be able to retain the manage of the visible/hidden status by the external checkbox if possible.
Full code is here
Instead of trying to save a reference to the labels that you are going to delete, and then re-selecting them, how about just use a variable that references the SerifText element selection, e.g.:
var SerifTextGroup = svg.append("g")
.attr("id", "serif-labels");
SerifTextGroup.selectAll("text")
.data(histogSerif)
.enter()
//... and so on
Then the rest of your code should work as written (just change SerifText to SerifTextGroup).

Labels on bilevel D3 partition / sunburst layout

I am trying to add labels to the bilevel sunburst / partition shown here - http://bl.ocks.org/mbostock/5944371:
I have added labels to the first 2 levels and rotated them correctly. But I cant now add the new level's labels during a transition. To get started I have put ...
text = text.data(partition.nodes(root).slice(1), function(d) { return d.key; });
straight after the ...
path = path.data(partition.nodes(root).slice(1), function(d) { return d.key; });
line but it throws the following error ...
Uncaught TypeError: Cannot read property '__data__' of undefined
What am I doing wrong?
I used bilevel partition to add labels via a mouseover, and found that in this version (unlike the other sunburst partition), there are two different sections where "path" is defined and updated. The first is here:
var path = svg.selectAll("path")
and then again below the transition you highlighted in your code:
path.enter().append("path")
When i added my mouseover labels, I needed to reference my text function in both places or it wouldn't work after transition.
If you can post your code to JSFiddle or bl.ocks.org we can try to play with it and see, but that was where I got tripped up at first.
Hope that helps.
*NOTE: Comment didn't post:
I'm sorry I'm not able to help more, but I'm also a newbie at D3. Here's where I got:
copy and paste your svg.selectAll("text") snippet after the second "path.enter().append("path") snippet. This will cause it to appear on subsequent zooms as well.
Problems I see: there's no "g" element so you need separate transitions for text as well or they all pile up. Also, I can't understand why they're positioned at their original partition spot instead of where the arc exists now.
My approach was add labels on mouseOver. I've uploaded that here: https://github.com/johnnymcnugget/d3-bilevelLabels
In this, I'm calling the two functions in both sets of "path" snippets, and the transitions are handled within the single variable of "legend"
Another D3 newbie, but I managed to resolve this. Beggining from the original Bilevel Partition:
Add the text for the first time the chart is drawn:
var path = svg.selectAll("path")
.data(partition.nodes(root).slice(1))
.enter().append("path")
.attr("d", arc)
.style("fill", function(d) { return d.fill; })
.each(function(d) { this._current = updateArc(d); })
.on("click", zoomIn);
var text = svg.selectAll("text")
.data(partition.nodes(root).slice(1))
.enter().append("text")
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
.attr("x", function(d) {return radius / 3 * d.depth; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.html(function(d) { return d.name; });
when zooming in or out you have to redraw labels, add the following in function zoom(root, p)
text.enter().append("text")
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
.attr("x", function(d) {return radius / 3 * d.depth; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d) { return d.name; });
text.exit().transition()
.style("fill-opacity", function(d) { return d.depth === 1 + (root === p) ? 1 : 0; })
.remove();
text.transition()
.style("fill-opacity", 1)
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
.attr("x", function(d) {return radius / 3 * d.depth; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
Finally modify the computeTextRotation function as:
function computeTextRotation(d) {
return (d.x + (d.dx)/2) * 180 / Math.PI - 90;
}
Hope I haven't missed anything.
Indeed one modified line is missing in "2.". In function zoom(root, p), you should also add a line after path = path.data(partition ... .key; });:
path = path.data(partition.nodes(root).slice(1), function (d) {
return d.key;
});
text = text.data(partition.nodes(root).slice(1), function (d) {
return d.key;
});

show data of each circle of bubble chart in table d3.js

I made a bubble chart and is working fine.But i need and even based feature in which i click on each circle and the data related to that circle will show in tabular form in another div..
<div id="bubblechart"></div>
<div id="table"></div>
first div contain the bubble chart and working fine. table div is used as container for the table generated.
here is my code.
var node = svg.selectAll(".node")
.data(bubble.nodes(classes(root))
.filter(function(d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.packageName); })
.on("mouseover", animateFirstStep)
.on("mouseout", animateSecondStep);
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.className; });
You can add an .on("click", clickFunction) to the node. This will work like your mouseover and mouseout lines.
In the clickFunction function, control the content of the target div using
document.getElementById('targetDiv').innerHTML = targetText;
or with jQuery
$("#targetDiv").html(targetText);

Resources