Black Lives Matter. Please consider donating to Black Girls Code today.
Learn how to use COVID-19 data in open source Dash apps. Register for the Sept 23rd webinar with IQT!

How to link hover event in 2D scatter to 3D scatter?

When I move my mouse in a 2D scatter plot, I want to show the corresponding point in a 3D scatter plot. How to do it?

I’m able to do the reverse event, which is linking 3D hover to 2D hover. Not sure why can’t I link 2D to 3D.

I have an error regarding these lines:

myPlot.on('plotly_hover', function (eventdata){
    var points = eventdata.points[0],
        pointNum = points.pointNumber;
    // console.log(points);
    Plotly.Fx.hover('myDiv2',[
        { curveNumber:0, pointNumber:pointNum },
    ]);
});

The error is:

Uncaught TypeError: Cannot read property ‘_subplot’ of undefined
at o (plotly-latest.min.js:58)
at Object.E.hover (plotly-latest.min.js:58)
at n. (link2d3d.html:68)
at n.emit (plotly-latest.min.js:16)
at HTMLDivElement.t.emit (plotly-latest.min.js:53)
at o (plotly-latest.min.js:58)
at Object.E.hover (plotly-latest.min.js:58)
at SVGRectElement.u.onmousemove (plotly-latest.min.js:58)

Here is my code: myDiv is a 2D plot and myDiv2 is a 3D plot.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <!--PLOTLY-->
	<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>


    <style>
        html, body {
            margin: 0px;
            padding: 0px;
            height: 100%;
            width: 100%;
        }
		
		#myDiv{
			height: 40%;
			width: 60%;
			position:relative;
		}
		#myDiv2{
			height: 40%;
			width: 60%;
			position:relative;
		}
    </style>
</head>
<body class='with-3d-shadow with-transitions'>

	<h2>JsonTest</h2>
	<div id="myDiv"></div>
	<div id="myDiv2"></div>
<script>

var data2d = [
{'marker': {'color': 'FFBAD2', 'line': {'width': 1}},
   'mode': 'markers',
   'type': 'scatter',
   'x': [1, 1, 2, 2],
   'y': [1, 2, 1, 2]}
];

var layout = {'title': 'First Plot',
    'hovermode':'closest'};

var data3d = [
{'marker': {'color': 'FFBAD2', 'line': {'width': 1}},
   'mode': 'markers',
   'type': 'scatter3d',
   'x': [1, 1, 2, 2],
   'y': [1, 2, 1, 2],
   'z': [1, 1, 1, 1]}
];



	var myPlot = document.getElementById('myDiv');
	var myPlot2 = document.getElementById('myDiv2');
	Plotly.plot('myDiv', data2d, layout);
	Plotly.plot('myDiv2', data3d, layout);
	

	myPlot.on('plotly_hover', function (eventdata){
    var points = eventdata.points[0],
        pointNum = points.pointNumber;
    // console.log(points);
    Plotly.Fx.hover('myDiv2',[
        { curveNumber:0, pointNumber:pointNum },
    ]);


	});

	myPlot2.on('plotly_hover', function (eventdata){
    var points = eventdata.points[0],
        pointNum = points.pointNumber;
    // console.log(points);
    Plotly.Fx.hover('myDiv',[
        { curveNumber:0, pointNumber:pointNum },
    ]);


	});	
</script>
</body>
</html>

still wating for a solution. Thanks :slight_smile:

Hi, sorry about the delay.

Plotly.Fx.hover can only trigger hover events on cartesian subplots at the moment.

You’ll have to draw your own hover labels on top of the 3D graph, unfortunately.

Could you show me an example how to draw hover labels on the 3D graph?

Or just guide me to the function name. I will try to figure it out.

Thank you

As Étienne said, it’s not currently supported, and it would be a difficult thing to do unless via developing plotly.js internals. If you’re planning to do so, the point picking mechanism in the 2D plots is an excellent guide, which you can study as it already works in plotly.js. You can study the code by putting a breakpoint where a pointer event is raised, inspecting the stack and seeing where it originally comes from, and immersing yourself in the 2D rendering code first.

The way point or line (or any) picking works is that a colored, but alpha-invisible layer is rendered, where points (or lines etc., let’s call them glyphs) are painted with unique colors. Then, upon mouse interaction on an x/y coordinate pair, the color of the pixel is read, and the reverse mapping between glyphs and colors give you the unique glyph id. Though each color is encoded in WebGL buffers as an 8-bit thing, i.e. giving a maximum of 256 distinct values, utilizing all three channels gives discernibility with a ceiling of 256^3 unique glyphs - but it requires packing/unpacking.

The benefit of this method is that this transparent layer is rendered with the same exact WebGL GLSL projection code as the visible things, so you don’t need to second-guess what glyph is where, and what occludes what.

From this, you also see it’d be practically impossible to achieve it externally, outside the plotly.js codebase and its dependencies e.g. in the gl-vis repo. It’s trivial to get an x/y coordinate on a DOM element such as the that backs the WebGL context. But the 3D scene can be moved, rotated, zoomed and one glyph may occlude another.

It’s known art yet a significant undertaking so it’s hard to schedule unless there’s a specific customer project. We also welcome pull requests to the plotly.js and gl-vis repos if there’s interest in taking a stab at it.

Thank you! It’s a little hard for me though.

I think I will stay with 2D hover to 2D hover.