React + d3 Tooltip Overlap With Legend - javascript

I have created a stacked and grouped bar chart with React + d3. The first time it loads you can click on any legend and it will toggle the graph. However, once you hover over and the graph and the tooltip is displayed, then the tooltip overlaps with the legend and you cannot click on legend to toggle anymore. The attached image shows how it overlaps.
The full code demo is demo
Please can anyone help?

z-index does not work in your case. But what works is setting height to 0 on mouseout and setting height back to auto on mouseover.
.on("mouseover", function (d, i) {
tooltip.transition().duration(50).style("opacity", 1).style("height", "auto");
})
.on("mouseout", function (d, i) {
tooltip.transition().duration(500).style("opacity", 0).style("height", "0%");
});

Related

Multiple tooltips not showing correctly in react

I am working with react D3 charts, and I have created charts and it is working fine.
What I have done
I have several charts which are updating with in some time intervals, something like live data
So here to achieve this I out use effect and updating my charts every second, and my data in charts updates correctly.
I have given one tooltip on hover over the the bar, so that user can check the data for each bar or line.
Using below code to show the tooltip
.on("mousemove", function (event, d) {
// this whole code is when I hover that perticular bar
d3.select(this)
.transition()
.duration("50")
.attr("opacity", 0.6)
.attr("x", (a) => xScaleBars(a.timeline) - 3)
.attr("width", xScaleBars.bandwidth() + 6)
.style("filter", "url(#glow)");
div.transition().duration(50).style("opacity", 1);
div
.html(
`</text><text"></br> value : ${d.dataToShow}
<br/>
</text><text"></br> Month : ${d.month}
`
)
.style("left", event.pageX - 58 + "px")
.style("top", event.pageY - 140 + "px");
})
.on("mouseout", function (d, i) {
// this is when I move cursor out of that bar
d3.select(this)
.transition()
.duration("50")
.attr("width", xScaleBars.bandwidth())
.attr("x", (a) => xScaleBars(a.timeline))
.style("filter", "none")
.attr("opacity", "1");
div.transition().duration("50").style("opacity", 0);
})
Issue I am facing
The issue is when I hover over one chart component it shows the tooltip, and than when I hover over the other both shows at the same time.
What I am trying to do is to show the tooltip when I hover the one bar of any chart and than hide it,I tried below code
d3.select("svg").selectAll(".tooltipCHart").remove();
But it doesn't resolve my issue, I think I am missing some small part
here is my code sandbox which I tried
The problem is that you're creating a new tooltip div every time you re-render the chart.
A better approach is to have a hidden tooltip div in the beginning (in the render / return from your function component) and then just modify its contents and style (opacity: 1) on mouseover and mouseout. Keep track of the tooltip div using a ref.
See working codesandbox (I only modified chart1, you can make similar changes to chart2)

Mouse out event not working properly in JavaScript D3

I am working with D3 Charts, and by all work I have completed the chart and did some enhancement as well.
What I am doing
I have one function which shows tooltip, whenever I hover over any bar I am showing some info to the user.
My chart shows live data, so if any new data is coming it automatically creates a new bar.
SO when I hover over any bar then data is showing fine and perfect
My issue
So as I mentioned above in my case the data comes after some interval continuously, so I am getting data and adding it to previous data
The issue is when i Hover the last bar the tooltip shows fine, and when the new data comes so now two tooltips showing and it goes on and on
But in my coding I am writing code to remove the tooltip on mouseout, but still getting this issue
My code
This is what I am doing
.on("mousemove", function (event, d) {
// this whole code is when I hover that perticular bar
d3.select(this)
.transition()
.duration("50")
.attr("opacity", 0.6)
.attr("x", (a) => xScaleBars(a.timeline) - 3)
.attr("width", xScaleBars.bandwidth() + 6)
.style("filter", "url(#glow)");
div.transition().duration(50).style("opacity", 1);
div
.html(
`</text><text"></br> value : ${d.dataToShow}
<br/>
</text><text"></br> Month : ${d.month}
`
)
.style("left", event.pageX - 58 + "px")
.style("top", event.pageY - 140 + "px");
})
This above code is when I hove rover
Below is the code when I do mouseout
.on("mouseout", function (d, i) {
// this is when I move cursor out of that bar
d3.select(this)
.transition()
.duration("50")
.attr("width", xScaleBars.bandwidth())
.attr("x", (a) => xScaleBars(a.timeline))
.style("filter", "none")
.attr("opacity", "1");
div.transition().duration("50").style("opacity", 0);
})
I have tried display none as well as visibility property, but nothing works
I don't know what I am doing wrong
is My code right or wrong this also I am not getting properly
I have put all of my code in code sandbox Please have a look
PS: I am using use Effect with set Timeout for each 1 second to make it update every second
I have checked all the related suggestion by stack overflow, but none helped me out may be I am wrong but I did not found the solution.
Edit / Update
The answer suggested below is not working, if I have more than once chart
I used d3.selectAll(".tooltipCHart").remove();
So when there are two charts on hover of first chart's bar it shows tooltip, but when I hover over the other chart it is not showing
Please have a look here
here in above code sandbox in first chart it does not show tooltip but in second it is showing
Vivek, I have gone through the code and found out that most of the code written is fine. Besides that the reason of multiple tooltips is that you are rendering everything whenever data changes, so you are appending the tooltip div everytime, it means below code will execute multiple times which display multiple tooltips in case where our code did not perform mouseout execution. You can check this by inspecting elements.
var div = d3
.select("body")
.append("div")
.attr("class", "tooltipCHart")
.style("opacity", 0);
Simple solution will be to remove all the tooltips before appending a new one.
d3.selectAll(".tooltipCHart").remove();
It will resolve the issue of multiple tooltips.
But for your chart my confusion is whether is it a good idea to show tooltip or not as the data is always moving toward left so it will be difficult to keep the tooltip for long time.

multiline tooltips show and hide d3.js

I am building a muti-series line chart which is very similar like this https://jsfiddle.net/xn1sLbf4/9/.
Now, I want to change the tooltips showing event. I want to have the tooltips show only when the vertical line is moving on the x-axis ticks instead of showing the tooltips on the entire line. For example, in my jsfiddle, when the vertical line locates at 'Mon 03', the tooltips show. If vertical line is moving between 'Mon 03' and 'Tue 04', tooltips hide. Can anyone give ideas how to accomplish this?
Thanks a lot!!
UPDATE
This is the change I made. See updated fiddle: https://jsfiddle.net/xn1sLbf4/10/
I changed the line 192-196 to
var mouseRect = mouseG.selectAll('.work-rect')
.data(newCities[0].values)
.enter()
.append("g")
.attr("class", "work-rect");
mouseRect.append('svg:rect')
.attr('x', function(d) { return x(d.date);})
.attr('width', 5)
.attr('y', function(d) { return 0;})
.attr('height',height)
.attr('fill', 'none')
The tooltips are showing only when the vertical line is on the ticks. But the vertical line also hide... How can I make the vertical line show all the time following the mouse across the chart?
If .style("opacity", "1") in mouseRect.append('svg:rect').on('mouseout', function() { is changed from 0 to 1 the mouse movement can be seen:
I understand your problem. You can just remove the following code from CSS file.
.x.axis path {
display: none;
}
Or
x.axis path { display: inline; }

Issue with overlapping toolitp d3.js

I found this is a very helpful example to create tooltip on line charts. I am following this to work on a line chart now. The difference is the tooltip in my chart has a box/background to contain the value showing in the tooltip, so I add append('rect') with attr('fill', 'white').
mousePerLine.append('rect').
attr('width', '38px').
attr('height', '20px').
attr('class', 'tooltipRect').
style('fill', 'white').
attr('transform', 'translate(5,-13)');
To avoid overlapping of text as well as rect, I changed line 292 according to a post here How to select multiple selectors with selectAll?
.select("text")
.attr("transform", function(d,i) {
return "translate (10,"+(3+ypos[i].off)+")";
})
to
.selectAll(".tooltipRect, text")
.attr("transform", function(d,i) {
return "translate (10,"+(3+ypos[i].off)+")";
})
Here's a fiddle of the problem.
However, the tooltips are still overlapping. Can anyone help to figure out what is the cause of the problem? Thanks in advance!
The rects keep overlapping likely because the way you are selecting them.
Why not close the selectiona at the text (keep the text selection above as is) but a make a new selection for the rect:
d3.selectAll(".mouse-per-line")
.select("rect")
.attr("transform", function(d,i) {
return "translate (5,"+(ypos[i].off - 13)+")";
});
This works for me.
I did the translation based on your initial set up of the rect. I adjusted the offset on line 286 from 15 to 20 - it looks a bit better.

Hiding a tooltip with transition in d3

I'm new to d3 and coding in general, and I'm making a social network graph with some tooltips. The tooltip is supposed to appear when someone hovers over a node and fade out and hide when the mouse is removed. I managed to get the tip to fade out with a transition, but the tip is actually still there, just invisible, so the box and text sometimes obscure other nodes, making it so that you can't successfully hover over parts of other nodes and trigger other tooltips. When the code is just node.on('mouseout', tip.hide);, it works fine, but it doesn't have the transitions.
Here's the fiddle. The effect I'm talking about doesn't happen there as much as in a normal browser though. http://jsfiddle.net/wPLB5/
node.on('mouseover', tip.show);
node.on('mouseout', function() {
d3.select(".d3-tip")
.transition()
.delay(100)
.duration(500)
.style("opacity",0);
tip.hide;
});
//node.on('mouseout', tip.hide); //This is the original line.
Edit:
I figured it out. I needed to add another style that I didn't know about. Here's the fixed code:
node.on('mouseout', function() {
d3.select(".d3-tip")
.transition()
.delay(100)
.duration(600)
.style("opacity",0)
.style('pointer-events', 'none')
});
I figured it out. I needed to add a pointer-events style. Here's the fixed code:
node.on('mouseout', function() {
d3.select(".d3-tip")
.transition()
.delay(100)
.duration(600)
.style("opacity",0)
.style('pointer-events', 'none')
});
You can try the two approaches using div tooltip or using svg title.
node.append("svg:title")
.text(function(d) { return "Location:" + " " + d.location +
"\nFloruit Date:" + " " + d.floruitDate; });
Also, maybe this answer will be useful for you D3: show data on mouseover of circle.

Categories