I have a D3 timeseries chart made up of line path and at each data point i use a circle which is appended to the lines. The circles have a mouse enter event attached to it and when the mouse is moved over the circle it displays the tooltip with the information about that data point and i also change the class of the circle so that it looks highlighted.
The problem i have got is, when the mouse is over the circle and the circle is highlighted and the tooltip is showing, at the same time if i get some new data and the chart is updated, the circle my mouse is over does not disappear even when the mouse is removed off the circle and it shows that circle hanging in the middle without being attached to any line. I have attached the image of the chart showing the problem.
Any help to fix this problem will be highly appreciated.
Here's the jsfiddle
code showing the issue. Try pointing your mouse to the circle and wait for the chart to update every 5 seconds
(Moving this from the comment section)
Take a look at this: https://jsfiddle.net/xvLgq8mn/
In the updateChart function you select by the circle
class:
// update the circles at each data points
svg.selectAll('.circle') // here you correctly select all with the circle class
.data(this.props.data)
.attr('class', 'circle all')
.transition()
.duration(500)
.attr('cx', (d) => { return this.axis.x(d.time);})
.attr('cy', (d) => { return this.axis.y(d.count);});
but here, on mouseover, you remove the circle
class and replace it with circle--highlight
:
group.selectAll()
.data(this.props.data)
.enter().append('circle')
.attr('class', 'circle all')
.attr('cx', (d) => { return this.axis.x(d.time);})
.attr('cy', (d) => { return this.axis.y(d.count);})
.attr('r', 4)
.on('mousemove', function(d) {
// START: Show tooltip
div.transition()
.duration(1000)
.style('opacity', 1);
div.html('<div class="date--time">'
+ d.time
+ '</div><div class="count">' + d.count + ' incidents</div>')
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY - 70) + 'px');
d3.select(this)
.attr('r', 6)
.attr('class', 'circle--highlight'); // here you change the class from circle all
// to just circle--highlight,
// so when you are hovering a circle and the chart changes,
// the circle you have hovered won't be updated because
// it won't be selected due to the class difference
// END: Show tooltip
})
.on('mouseleave', function() {
// hide tooltip and return the circles to original style
div.transition()
.duration(500)
.style('opacity', 0);
// set the circle back to normal
d3.select(this)
.attr('r', 4)
.attr('class', 'circle all');
});
So a solution would be to also add the circle
class along with the circle--highlight
like this:
d3.select(this)
.attr('r', 6)
.attr('class', 'circle circle--highlight');
Or change your select in the updateChart like this:
svg.selectAll('circle')
but that would need many more adjustments to your script in order for it to work as expected.
Hope this helps! Good luck!