Adding labels to the middle of a sunburst on mouseover - javascript

I've been working on a sunburst visualization example provided by the following link http://bl.ocks.org/mbostock/4063423. I want the label to display the name of the partition in question that has been moused over. Right now whenever I mouseover a partition it shows "flare" in the middle only. Is there a way for me to access the names of the children?
d3.json("flare.json", function(error, root) {
var path = svg.datum(root).selectAll("path")
.data(partition.nodes) //access the nodes
.enter()
.append("path")
.attr("display", function(d) { return d.depth ? null : 'none';}) //hide inner ring
.attr("d", arc)//used whenever I come across a path
.style("stroke", "#fff")
.style("fill", function(d) { return color((d.children ? d : d.parent).name);})
.style("fill-rule", "evenodd")
.each(stash)
.on("mouseover", mouseover)
.on("mouseout", mouseout);
var label = svg.append("text")
.attr("id", "tooltip")
.attr("x", 10)
.attr("y", 50)
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("font-weight", "bold")
.attr("fill", "black")
.style("opacity", 0)
.text(function(d) { return d.name; });
function mouseover(d) {
d3.select(this)
.transition()
.duration(100)
.style("opacity", 0.3);
label.style("opacity", .9);
console.log('mouseover', mouseover);
};
function mouseout(d) {
d3.select(this)
.transition()
.duration(100)
.style("opacity", 1);
label.style("opacity", 0);
console.log('mouseout', mouseout);
};

This problem is solved by first of all appending text elements to a g element and not svg element. Second you want to create a text element outside the mousehandler with a specific id then call it using that Id within the event handler like so.
d3.json("flare.json", function(error, root) {
var g = svg.selectAll("g")
.data(partition.nodes(root))
.enter().append("g");
var path =
g.append("path")
.attr("display", function(d) { return d.depth ? null : 'none';}) //hide inner ring
.attr("d", arc)//used whenever I come across a path
.attr("id", "part")
.style("stroke", "#fff")
.style("fill", function(d) { return color((d.children ? d : d.parent).name);})
.style("fill-rule", "evenodd")
.each(stash)
.on("mouseover", mouseover)
.on("mouseout", mouseout);
var text = g.selectAll("text")
.data(partition.nodes(root))
.enter()
.append("text")
.attr("id", "tip")
.attr("x", 10)
.attr("y", 50)
.attr("font-size", "11px")
.style("opacity", 0);
function mouseover(d) {
d3.select(this)
.transition()
.duration(1000)
.ease('elastic')
.style("opacity", 0.3);
//label.style("opacity", .9);
d3.select("#tip").text(d.name).style("opacity", 0.9);
console.log('mouseover', mouseover);
};
function mouseout(d) {
d3.select(this)
.transition()
.duration(100)
.style("opacity", 1);
d3.select("#tip").text(d.name).style("opacity", 0);
console.log('mouseout', mouseout);
};

Related

How to show values in a tooltip

I've built a network graph and I want to show the information from the data source in my tooltip based on the circle you hover over. Currently, my hover action to turn the circle red works, but my tooltip just shows the same value regardless of where you hover. I'm confused as to where I'm going wrong and how to rectify this. Any help would be appreciated. Here's my code below:
const node = svg.append("g")
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", 0.4)
.attr("fill", "#f2d974")
.attr("fill-opacity", 0.4);
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
var tooltip = d3.select("#france")
.append("div")
.data(nodes)
.style("position", "absolute")
.style("visibility", "visible")
.style("background", "white")
.style("border", "solid")
.style("border-width", "0.5px")
.style("border-radius", "5px")
.style("padding", "5px")
.style("width", "100px")
.style("height", "100px")
.text(d=>d.id)
console.log(d=>d.id)
node
.on("mousemove", function(d){
console.log(d)
d3.select(this).style("fill", "red")
tooltip.style("visibility", "visible")
.style("top", (event.pageY))
.style("left", (event.pageX))
.text(d=>d.id)
})
.on("mouseout", function(){
tooltip.style("visibility", "hidden")
})
You are always seeing the same value because you are using the data element from the tooltip:
tooltip.style("visibility", "visible")
.style("top", (event.pageY))
.style("left", (event.pageX))
.text(d=>d.id) // -> this is the d.id binded to the tooltip
Your issue is a shaded variable
Can you try this code and let me know if it works:
tooltip.style("visibility", "visible")
.style("top", (event.pageY))
.style("left", (event.pageX))
.text(d.id)

How to add text to paths

I suspect I'm barking up the wrong tree - although I've got no errors in the console to help me out.
I've got this block of code:
var path = svg.data([json]).selectAll("path")
.data(partition.nodes)
.enter()
.append("path")
.attr("display", function(d) {
return d.depth ? null : "none";
})
.attr("d", arc)
.style("stroke", "#fff")
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.attr("fill-rule", "evenodd")
.style("opacity", 1)
.each(stash);
//>>this section functions ok
path.append("title")
.text(function(d) {
return d.name + ": " + d.amount;
});
//>>this section throws no errors but "foo" does not appear
path.append("text")
.text(function(d) {
return "foo";
})
.style("stroke", "#3b5998")
.style("fill", "#3b5998");
The code snippet beginning path.append("title")... works ok but the final snippet beginning path.append("text")... adds the text foo to the html but it is not visible on the webpage - why is it not visible and how do I add labels?
This is part of this visual:
http://plnkr.co/edit/q9ODd5?p=preview
text cannot be nested with a path. You'll need to add it to the svg instead. Additionally, you'll want to position the text in some way:
svg.append("text")
.text(function(d) {
return "foo";
})
.attr("x", function(){ return 0 })
.attr("y", function(){ return 0 })
.style("stroke", "#3b5998")
.style("fill", "#3b5998");
The working code ended as the following:
var path = svg.data([json]).selectAll(".theArc")
.data(partition.nodes)
.enter()
.append("path")
.attr("class", "theArc") //<<<<<<<<<<new
.attr("id", function(d,i) { return "theArc_"+i; }) //Give each slice a unique ID //<<<<<<<<<<new jq
.attr("display", function(d) {
return d.depth ? null : "none";
})
.attr("d", arc)
.style("stroke", "#fff")
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.attr("fill-rule", "evenodd")
.style("opacity", 1)
.each(stash);
path
.append("title") //mouseover title showing the figures
.text(function(d) {
return d.name + ": " + d.amount;
});
svg.data([json]).selectAll(".theTxts")
.data(partition.nodes)
.enter()
.append("text")
.attr("class", "theTxts")
.attr("dx", 10) //Move the text from the start angle of the arc
.attr("dy", 18) //Move the text down
.append("textPath")
.attr("xlink:href", function(d, i) {
return "#theArc_" + i;
})
.text(function(d) {
return d.name;
})
.style("stroke", "#3b5998")
.style("fill", "#3b5998");

updating text position on pie chart update

I've been trying to adapt this design into a dynamic pie chart.
Everything has gone reasonably well aside from getting the text to reposition on update.
In the example below, I am first removing the text label and then redrawing, I don't think this is the best way to do it, I was trying to approach it with the code that is commented out just underneath but have been unsuccessful.
Plunk
Offending code;
function updatePath() {
g = svg.datum(donutData).selectAll(".arc")
.data(pie)
g.select("path")
.transition()
.duration(750)
.attrTween("d", arcTween) // redraw the arcs
svg.selectAll(".donutText").remove()
pieTextLabel()
}
// Attempt 1 Below
/*
svg.selectAll(".donutText")
.style("opacity", 0)
.attr("dy", 18)
.append("textPath")
.attr("startOffset", "50%")
.style("text-anchor", "middle")
.attr("xlink:href", function(d, i) {
return "#donutArc" + i;
})
.text(function(d) {
return d.value;
})
.transition()
.duration(1000)
.style("opacity", 1);
*/
function pieTextLabel() {
var selectText = svg.selectAll(".donutText")
.data(donutData)
selectText
.enter().append("text")
.attr("class", "donutText")
.attr("dy", 18)
.append("textPath")
.attr("startOffset", "50%")
.style("text-anchor", "middle")
.attr("xlink:href", function(d, i) {
return "#donutArc" + i;
})
.text(function(d) {
return d.value;
});
selectText.exit().remove()
}
function drawPie() {
var g = svg.selectAll(".donutArcSlices")
.data(pie(donutData))
.enter().append("g")
.attr("class", "arc");
var path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color(d.data.label);
})
.each(function(d, i) {
this._current = d;
var firstArcSection = /(^.+?)L/;
var newArc = firstArcSection.exec(d3.select(this).attr("d"))[1];
newArc = newArc.replace(/,/g, " ");
svg.append("path")
.attr("class", "hiddenDonutArcs")
.attr("id", "donutArc" + i)
.attr("d", newArc)
.style("fill", "none");
})
}
Having trouble cracking this - any help/advice is much appreciated!
Thanks
It's because you didn't update the path
First delete the old path
svg.selectAll("path").remove()
Then recreate it
var path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color(d.data.label);
})
.each(function(d, i) {
this._current = d;
var firstArcSection = /(^.+?)L/;
var newArc = firstArcSection.exec(d3.select(this).attr("d"))[1];
newArc = newArc.replace(/,/g, " ");
svg.append("path")
.attr("class", "hiddenDonutArcs")
.attr("id", "donutArc" + i)
.attr("d", newArc)
.style("fill", "none");
})
see http://plnkr.co/edit/WTuX38GCgIFLFfc1QPVv?p=preview

mouseover doesn't work on d3 rectangle

I am new at d3. I have written the below code for 3 rectangles to appear and make them have some mouse interaction.
svg.append("g").selectAll("rect")
.data([1,2,3])
.enter()
.append("rect")
.attr("x",function(d,i){return 600+i*50;})
.attr("y",30)
.attr("width",40)
.attr("height",40)
.attr("fill","blue")
.on("mouseover",function(d) {
d3.select(this).append("text")
.attr("y", "100")
.attr("x", "500")
.attr("class", "hover")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.style("fill", "black")
.text(function(d){console.log("mouseover");
return "Text I want";})
})
.on("mouseout", function(d) {
d3.select(this).select("text.hover").remove();
})
.on("click",function(d){console.log(d);
if(d==1)
Pie(array1,array2);
if(d==2)
Pie(array3,array4);
if(d==3)
Pie(array5,array6);
})
.style("opacity",1e-6)
.transition()
.duration(1000)
.style("opacity",0.8);
The console.log("mouseover") appears at the console, but no text is shown at the browser. The click event works with pie charts being constructed. Can anybody spot what is going wrong? Thank you in advance.
In your mouseover:
d3.select(this).append("text")
would append the text to the rect but rect elements can not have children.
Changing it to:
svg.append("text")
works. Full code example:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var svg = d3.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 500);
svg.append("g").selectAll("rect")
.data([1, 2, 3])
.enter()
.append("rect")
.attr("x", function(d, i) {
return 10 + i * 50;
})
.attr("y", 30)
.attr("width", 40)
.attr("height", 40)
.attr("fill", "blue")
.on("mouseover", function(d) {
svg.append("text")
.attr("y", "100")
.attr("x", "200")
.attr("class", "hover")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.style("fill", "black")
.text(function(d) {
console.log("mouseover");
return "Text I want";
})
})
.on("mouseout", function(d) {
svg.select("text.hover").remove();
})
.on("click", function(d) {
console.log(d);
if (d == 1)
Pie(array1, array2);
if (d == 2)
Pie(array3, array4);
if (d == 3)
Pie(array5, array6);
})
.style("opacity", 1e-6)
.transition()
.duration(1000)
.style("opacity", 0.8);
</script>
</body>
</html>
I think you should use d3-tip module for d3. It provides very nice hover tooltip
http://bl.ocks.org/Caged/6476579
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Frequency:</strong> <span style='color:red'>" + d.frequency + "</span>";
})
and on bars or rectangles use
.on('mouseover', tip.show)
.on('mouseout', tip.hide)

JS D3 textPath isn't displayed

i have the code below and wonder, why the textpath isn't displayed? Can anyone help?
var areas = svg.append("g").selectAll("path")
.data(chord.groups)
.enter().append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("class", "bar")
.attr("id", function(d, i) { return "group" + i; })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
svg.selectAll(".bar").append("text")
.style("font-size", "10px")
.attr("fill", "black")
.append("textPath")
.attr("x", 8)
.attr("dy", ".35em")
.style("fill", "#ff00ff")
.attr("xlink:href", function(d, i) { return "#group" + i; })
.text("Textexample");
Thank you very much!
Benjamin

Categories

Resources