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; }
Related
I am creating a population map of the US. I have the map and legend working, but I made a drop down menu that allows me to filter by race. This works and changes the data on the map and legend, but I am having an issue where the legend text shows the new range, and all previous ranges as I change the drop down menu. Is there a way to have it so that it doesn't overlap the previous text but instead shows only the one correct text? I am using D3 with React.
This is the code to my legend:
svg.append("g")
.attr("transform", "translate(580,20)")
.append(() => Legend(color, {title: `2019 Population (x10^${exp})`, width: 300,tickFormat: ".1f"}))
The code to my color variable:
const color = d3.scaleQuantile([start/divider,end/divider], d3.schemeYlOrRd[9])
start and end change depending on how big the population sizes are
Edit/Update:
I found a work around to solving my issue, I'm just not sure if its best practice or if there's another way of doing it. I gave it a background color so that the previous info gets covered up
code:
svg.append("g")
.attr("transform", "translate(580,20)")
.append(() => Legend(color, {title: `2019 Population (x10^${exp})`, width: 300,tickFormat: ".1f"}))
.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "grey")
svg.append("g")
.attr("transform", "translate(580,20)")
.append(() => Legend(color, {title: `2019 Population (x10^${exp})`, width: 300,tickFormat: ".1f"}))
Every time you do svg.append('g').transform(...).append(() => Legend()) you are adding a new <g> element.
Instead store the <g> selection in a variable and then remove its contents before adding a new legend.
const legendG = svg.append('g').attr('transform', 'translate(580, 20)')
function renderLegend(legendOptions) {
legendG.selectAll('*').remove() // removes everything inside
legendG.append(() => Legend(legendOptions))
}
// now call the `renderLegend` function every time you change something from the menu
And to answer your question if what you did is a good practice. I would say it is not, because you're just adding elements every time the user chooses something in the menu and it's just taking up more and more memory for storing the DOM. Not good for performance.
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)
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%");
});
I'm working on a force directed layout. When I first started on this, I had the colors defined in CSS and it worked great. Somewhere along the way I decided to try the built-in D3 color scale, but when I tried to go back to my custom CSS colors, the code doesn't run without the color scale line anymore. Somehow I'm "stuck" with the d3 scale - line 4 of this code: https://jsfiddle.net/lilyelle/gwacm7z5/
var w = 600,
h = 500,
r = 30,
fill = d3.scale.category10()
;
I know my CSS is working because my pointer-events command is working - but somehow the rest of the CSS will not apply color to my elements. Can anyone help with getting rid of the d3 scale and returning to regular CSS styling???
Thank you!
You CSS should be:
.node .type1 {
fill:#690011;
}
.node .type2 {
fill:#BF0426;
}
And then when creating your circles:
node.append("circle")
.attr("r", 35)
.attr("class", function(d){
return "node type" + d.type;
})
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
Updated fiddle.
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.