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)
Related
I am working with this icicle visual on D3 Observable. I need to add a tooltip, so that it works faster and looks better than native browser version.
I tried this:
var tooltip = d3.select("body")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px");
var mouseover = function(d) {
tooltip
.style("opacity", 1)
};
var mousemove = function(d) {
tooltip
.html("hello")
.style("left", (d3.mouse(this)[0]+90) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
};
var mouseleave = function(d) {
tooltip
.transition()
.duration(200)
.style("opacity", 0)
};
And adding the events onto the rect:
.on("mouseover", mouseover)
.on("mousemove", mousemove )
.on("mouseleave", mouseleave)
Nothing shows up at all when you hover over the rects of the visual. Can elements be appended to the body in D3 observable?
I would like to ask if anyone know how to get the code to do similar chart like this https://www.theguardian.com/world/interactive/2013/feb/12/state-of-the-union-reading-level
It is written in D3 but I couldn't find similar codes online.
Thanks
I think this is just a fairly involved tooltip on a scatter plot. Here's a simpler example:
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
You might also find this other example useful.
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);
};
I draw a line graph using D3.js and i am using tooltip in line graph,but i am also using tooltip in legends but enable to show the tooltip in legends,i wrote given code,it is possible to show the tooltip in legends.
var dates=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];
var legend = canvas.append("g")
.attr("class", "legend")
// .attr("transform", "translate(70,10)");
var legendRect = legend.selectAll('rect').data(dates);
legendRect.enter()
.append("rect")
.attr("x", function (d,i){return i*14;})
.attr("width", 12)
.attr("height", 20)
.attr("y", 10)
.style("fill","steelblue")
legend.selectAll("text")
.data(dates)
.enter()
.append("text")
.attr("x", function (d,i){return i*14;})
.attr("y", 25)
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white")
.text(function(d) {
return d;
})
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(formatTime(d.key) + "<br/>" + d.value)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY-28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
Iam adding tooltip in text but enable to show the tooltip in my values(I have only problem in legend tooltip)
Check out this code. It does exactly what you want.
This is also a great example.
I made a line graph with d3.js (see the attached image1).
I managed to insert tooltips on graph dots when mouseover.
I'd like to change color and size of dots too. I tried in many ways but it seems really difficult. Any help?
Here is the piece of code:
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5.5)
.style("fill", "#fff8ee")
.style("opacity", .8) // set the element opacity
.style("stroke", "#f93") // set the line colour
.style("stroke-width", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
div.transition()
.duration(70)
.style("opacity", .7)
;
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(200)
.style("opacity", 0);
});
Just set color and size in the handlers:
.on("mouseover", function(d) {
d3.select(this).attr("r", 10).style("fill", "red");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#fff8ee");
});
I don't know why, but while d3.select(this) used to work, it doesn't anymore. I now use d3.select(event.currentTarget).
So, if we consider svg as the graph and all its circles being red by default, we can change the color of the circles to green on mouseover and return the color to red on mouseout like this:
svg.on("mouseover", function(d){
d3.select(event.currentTarget)
.style("fill", "green");
})
.on("mouseout", function(d){
d3.select(event.currentTarget)
.style("fill", "red");
});