Skip to content

Spike line on the wrong subplot on multi-subplot Fx.hover calls #3219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chenzhiw opened this issue Nov 6, 2018 · 3 comments
Closed

Spike line on the wrong subplot on multi-subplot Fx.hover calls #3219

chenzhiw opened this issue Nov 6, 2018 · 3 comments
Labels
bug something broken

Comments

@chenzhiw
Copy link

chenzhiw commented Nov 6, 2018

Deploy #301 on subplots can display all the point info when hover on any subplot. But if the trace data of two subplots are close, the spike line may be in the wrong subplot.

https://codepen.io/anon/pen/vQOrMj
Put cursor on (19, 119) point of trace0, the spike line of yaxis is in the trace1 plot.

@etpinard
Copy link
Contributor

etpinard commented Nov 6, 2018

got it

peek 2018-11-06 17-20

thanks for the report.

@etpinard etpinard added the bug something broken label Nov 6, 2018
@etpinard etpinard changed the title spike line on the wrong subplot Spike line on the wrong subplot on multi-subplot Fx.hover calls Dec 21, 2018
@ghost
Copy link

ghost commented Feb 5, 2020

Edit: Try this workaround:

if (eventdata.xvals) { Plotly.Fx.hover(graph, { xval: eventdata.points[0].x, yval: eventdata.points[0].y }, ['xy', 'xy2']); }
Using the points[] array to get the x coordinate, and also providing a y coordinate (both of these, together), seems to fool it into working.

This does not work properly when multiple traces share one of the stacked yaxes - it will always choose the first trace on that axis. In order to work around this, we need to find the point nearest the values given to us.

Since codepen requires captcha spyware I cannot create an account, so here is the above code, modified with the workaround:


var trace1 = {.... copy from the original, too long for here.
};

var trace2 = {.... copy from the original, too long for here.
};

var data = [trace1, trace2];

var layout = {
  grid: {rows: 2, columns: 1, pattern: 'coupled', ygap: 0.2, subplots:['xy','xy2']},
  height: 500,
  xaxis: {range:[0,500],spikesnap:'data'},
  yaxis1: {range:[0,1000],spikesnap:'data'},
  yaxis2: {range:[0,1000],spikesnap:'data'},
  spikedistance: -1,
};

Plotly.newPlot('div1', data, layout);

graph = document.getElementById('div1');
graph.on('plotly_hover', function(eventdata) {
		//Hover all axes
			var evt = {};
			targetpoint = 0;
			leastdiff = Infinity;
			// Find the closest point to the vals returned
			for (i = 0; i < eventdata.points.length; i++) {
				diff = Math.abs(eventdata.points[i].y - eventdata.yvals[0]);
				if (diff < leastdiff) {
					targetpoint = i;
					leastdiff = diff;
				}
			};
			
			evt.xval = eventdata.points[targetpoint].x;
			evt.yval = eventdata.points[targetpoint].y;
			
			Plotly.Fx.hover(
				graph, 
				evt,
				Object.keys(plotdiv._fullLayout._plots),
			);
});

I'll leave my original comment in place, since the more I look into this, the more problems with hover() I seem to find XD
Anyway, this is a dirty workaround but it will do for my needs, and hopefully help you too, OP

Original comment follows:

This also effects hover labels in 'closest' mode.

I wanted to make a contribution to fix this but it seems that it runs pretty deep, and that multiple subplots which are not overlaid are not really part of the original design.
The core of this is that a) a target is not provided, so there's no way for the function to know which subplot we are hovering, and if you provide one, the function assumes that it was called by a real mouse movement (which may or may not actually cause problems but is clearly not the intended use of the function); and b) even with the target provided, the function(s) are built under the assumption that the subplots share the same space (ie they are overlaid), ie, all distances for hovering and spikelines are calculated based on the individual subplots' x|yval and ignore that two or more of the exact same vals might not actually be in the same place - the target is not used to calculate the difference in position for each subplot.

Perhaps this could be fixed by shifting the x|yval values, according to the axes' _offset values, when multiple subplots are specified? I imagine that should still work as intended when using 'x' or 'y' hovermodes, and 'closest' would now work as intended... but it might break 'compare' (?) and I can see numerous places where this could be done anyway.

Given that this is nontrivial and has been sitting here for a year, and I've read that Fx.hover might just go away in v2 (what's v2? lol) I wonder if it's even worth investing my time? I've already spent a day or so on it and have learned enough to know it's not straightforward and I think I know why it's been sitting here for so long ;)

@gvwilson
Copy link
Contributor

Hi - this issue has been sitting for a while, so as part of our effort to tidy up our public repositories I'm going to close it. If it's still a concern, we'd be grateful if you could open a new issue (with a short reproducible example if appropriate) so that we can add it to our stack. Cheers - @gvwilson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken
Projects
None yet
Development

No branches or pull requests

3 participants