# Capturing mouse events/position

**URL:** <https://community.plotly.com/t/capturing-mouse-events-position/4616>\
**Category:** Dash Python\
**Created:** [June 25, 2017, 2:47pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616 "2017-06-25T14:47:03Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [June 25, 2017, 2:47pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/1 "2017-06-25T14:47:03Z")

</div>

Hey everybody,

I was playing over the last days with the new Dash library and came across the following problem:  
Is there a way, to get the mouse position over the graph and e.g. draw a vertical line at the position of the mouse?

I want to create something similar to the left four figures of [this beautiful data viz](http://www.tylernwolf.com/#/portfolio/corrdisp). So what I have are different time series that I would like to plot in a stack and then one vertical line, that crosses all of them and annotates at the intersect of the vertical line with each graph line. I’m not quite sure, if this is possible with the new library, but maybe someone has an idea.

Many thanks in advance!

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [June 25, 2017, 5:02pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/2 "2017-06-25T17:02:55Z")

</div>

I found an solution for at least the mouse position. There is a property of an dcc.Graph called ‘hoverData’ that can be retrieved via @app.callback. hoverData stores the x and y position and with them a line can plotted easily. Here some basic code example:

But it is quite slow compared to plain Javascript…

```python
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go

import numpy as np

x_data = np.linspace(0,500,500)
y_data = np.random.rand(500)
height = max(y_data)

app = dash.Dash()

app.layout = html.Div([
    dcc.Graph(id='basic_graph')])

@app.callback(dash.dependencies.Output('basic_graph', 'figure'),
              [dash.dependencies.Input('basic_graph', 'hoverData')])
def update_graph(hoverData):
    if not hoverData:
        x_value=x_data[250]
        opacity = 0
    else:
        x_value = hoverData['points'][0]['x']
        opacity = 0.8
    data = [go.Scatter(
                x=x_data,
                y=y_data,
                line={'color': '#235ebc'},
                opacity=0.8,
                name="Graph"
            ),
            go.Scatter(
                x=[x_value, x_value],
                y=[0, height],
                line={'color': '#a39999'},
                opacity=opacity,
                name='Moving Line')
            ]
    layout = go.Layout(
                xaxis={'type': 'linear', 'title': "Timestep"},
                yaxis={'type': 'linear', 'title': "Value"},
                margin={'l': 60, 'b': 40, 'r': 10, 't': 10},
                hovermode="False"
                )
    
    return {'data': data, 'layout': layout}

if __name__ == ' __main__':
    app.run_server()

```

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [June 26, 2017, 5:53pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/3 "2017-06-26T17:53:22Z")

</div>

Nice find! Yes, `hoverData` is the way to this right now.

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [June 26, 2017, 9:41pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/4 "2017-06-26T21:41:10Z")

</div>

@chriddyp but it’s really laggy. I first thought it’s maybe because I unnecessarly repaint all three graph’s on each callback event, but even when I tried only to visualize a single moving line under the mouse, it’s really laggy. Talking about ~3-5 updates per second. Far away from JS performance.

You have any tip on improving the performance? Although it’s such a simple example, I don’t know where to improve it.

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [June 26, 2017, 10:46pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/5 "2017-06-26T22:46:49Z")

</div>

@fkratzert - it’s hard to say without seeing all of the code.

For reference, here’s an example from the announcement that feels pretty quick. It’s filtering a dataframe on every mouse hover and then displaying info about the point in the text box. The code for this example is here: [https://github.com/plotly/dash-docs/blob/master/tutorial/examples/walmart.py](https://github.com/plotly/dash-docs/blob/master/tutorial/examples/walmart.py)

 ![](https://cdn-images-1.medium.com/max/800/1*xeQbH0GDSmFq14f2-q4qdw.gif)

Does it feel or look significantly slower than that?

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [June 27, 2017, 7:05am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/6 "2017-06-27T07:05:36Z")

</div>

@chriddyp Unfortunately yes. I saw this examples and therefore was quite surprised that drawing a graph seems to take so much more time, compared to writing a text box. I posted a complete working code example above. And already for this code, the update is quite laggy. Maybe you can copy the code and try to run it on your local machine.

I thought the issue could be, that on each callback event I don’t only update the moving line, but update the entire graph content (having not only the moving vertical indicator line, but also the “static” graph). But then I tried in a different example to just have one moving line in one graph without anything else, and already this simplest example is quite laggy. You could try this second example by simply removing the blue’ish graph showing the random numbers from the above code example.

Would be glad to get any feedback!

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [June 27, 2017, 2:26pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/7 "2017-06-27T14:26:35Z")

</div>

Ah I see. Yes, here is how that example looks on my machine. It’s definitely not instantaneous.

 ![](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/1/19ce329a50600fd3c15d8348e1480a7fdab758b4.gif)

Right now, the graph is redrawing itself on every update. Eventually, I’d like to update the `dash_core_components.Graph` component to take a diff of the data and use `Plotly.restyle` instead of `Plotly.newPlot` to only redraw the parts of the graph that have changed, rather than the entire graph. That should make updates quite a bit faster.

Using `go.Scattergl` (web-gl enabled plot) instead of `go.Scatter` (SVG rendered) will make it faster for large datasets as well.

If there are any companies out there that would like to expedite this work through sponsorship, [please reach out](https://plot.ly/products/consulting-and-oem/)!

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [June 28, 2017, 8:36am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/8 "2017-06-28T08:36:54Z")

</div>

@chriddyp Thanks for your testing and the \*gif. Although it looks a bit smoother using webgl, it’s far away from good fluent user experience. Here is a comparable example in plain JS using d3 library.  
(sorry for the bad quality gif)

![](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/d/d3827b8cd525b5f9b5111d4b93f1e336534043c5.gif)

For this example, there was some “animation fading” implemented, this is, why the line seems to be slightly behind the mouse. But I guess it’s clear to see what kind of performance, I was hoping to get by Dash.

I think, it would be really nice, if there are efforts to improve these kind of animations, because I think they are used in many data visualization tools (having a moving maker I mean).

There is this built-in Plotly “Toggle Spike Lines” function in each Graph, that does nearly what I want and is pretty fast, but not customizable. Let me know if I can help with some test or anything, because I can’t afford a sponsorship on my own 😉

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [June 28, 2017, 4:48pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/9 "2017-06-28T16:48:40Z")

</div>

Thanks for the example! For more “standard” types of interactions like these (spike lines) that don’t require custom Python callbacks, the best solution might be to implement them in JS. There are two ways this can happen:

1 - Implement the feature in plotly.js. We don’t want to bloat the library and documentation with too many custom interaction features so these features need to be designed and abstracted pretty artfully. One can discuss this in the plotly.js repo by creating an issue: [http://github.com/plotly/plotly.js/issues](http://github.com/plotly/plotly.js/issues). It’s helpful to include as many examples as possible and to take a stab at what the attributes might look like (e.g. `layout.hovermode = verticalspikelines`, `layout.spikelinemode = displayvalues`).

2 - Eventually, I’d love it if `plotly.js` allowed for entirely customized `hover` and `select` style properties so that you could design custom hover lines like this. Spikelines could benefit from this and so could custom marker-hover interactions (e.g. make the markers darker or bigger and bolder when you hover over them). I’ll create an issue in `plotly.js` about this. If `plotly.js` doesn’t take this on, perhaps `dash-core-components` will.

3 - Alternatively and immediately, you could design your own Graph component in JS that would turn on these spikelines with a special attribute. Here are the docs on creating your own components: [https://plot.ly/dash/plugins](https://plot.ly/dash/plugins), here is a tutorial on React and plotly.js: [https://academy.plot.ly/](https://academy.plot.ly/), and here is the existing `Graph` component that you can base it off of or fork: [https://github.com/plotly/dash-core-components/blob/master/src/components/Graph.react.js](https://github.com/plotly/dash-core-components/blob/master/src/components/Graph.react.js). As you play around with it, these changes could get folded back into the main `dash-core-components` library or serve as inspiration for `plotly.js`. At a high level, it would:

- Add a hover listener after the graph is drawn (`Graph.react.js` already does this so you can copy that code)
- On hover, extract the data and call a `Plotly.relayout` with a vertical line and an annotation

Hope that helps! Thanks again for the example and the ideas 🙂

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [July 4, 2017, 5:48pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/10 "2017-07-04T17:48:07Z")

</div>

I have created an issue for this in plotly.js: [https://github.com/plotly/plotly.js/issues/1847](https://github.com/plotly/plotly.js/issues/1847)

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [July 5, 2017, 6:56am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/11 "2017-07-05T06:56:31Z")

</div>

@chriddyp thank you very much for the effort you put into my issue! Unfortunately I think my JS isn’t profound enough to help with the development but when there is anything python related I’ll be glad to help. Anyway I will follow the conversation on github and see if I can help with anything!

---

<div class="post-metadata">

**Author:** ![jimmybow](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jimmybow/32/6281_2.png) [@jimmybow](https://community.plotly.com/u/jimmybow)\
**Post date:** [July 18, 2017, 12:55pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/12 "2017-07-18T12:55:20Z")

</div>

I try a way to get mouse position by adding mouse listener, and upload it 🙂  
[https://pypi.python.org/pypi?%3Aaction=display&name=mydcc&version=0.0.3](https://pypi.python.org/pypi?%3Aaction=display&name=mydcc&version=0.0.3)

you can pip install it 😊

Usage :

```
app.layout = html.Div([
    mydcc.Listener(id = "uuu"),
    dcc.Graph( id = 'ggg',
               figure = { 'data': [{'x': [1, 2, 3], 'y': [4, 1, 2]} ]
                         }
              )       
])

@app.callback(
    Output('uuu', 'aim'),
    [Input('ggg', 'id')])
def update_figure(x):
    return x
```

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [July 18, 2017, 8:32pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/13 "2017-07-18T20:32:03Z")

</div>

@jimmybow hey jimmy, thanks for your reply. Unfortunately I can’t test your package at the moment. You mind adapting the code from above and grab a .gif/share information about the performance of your implementation? Buy this we could compare (at least a bit) the different approaches.  
Many thanks in advance

---

<div class="post-metadata">

**Author:** ![jimmybow](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jimmybow/32/6281_2.png) [@jimmybow](https://community.plotly.com/u/jimmybow)\
**Post date:** [July 19, 2017, 2:33am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/14 "2017-07-19T02:33:39Z")

</div>

can’t you install it …? i can run in win10 🤔

I use the way of gd.addEventListener(‘mousemove’, function) from javascript, the performance is well  
here is the source react.js code [https://github.com/jimmybow/mydcc/blob/master/src/components/Listener.react.js](https://github.com/jimmybow/mydcc/blob/master/src/components/Listener.react.js)

---

<div class="post-metadata">

**Author:** ![jimmybow](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jimmybow/32/6281_2.png) [@jimmybow](https://community.plotly.com/u/jimmybow)\
**Post date:** [July 19, 2017, 11:14pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/15 "2017-07-19T23:14:17Z")

</div>

version 0.0.3 is unavailable… please use version 0.0.8 😊

[https://pypi.python.org/pypi?%3Aaction=display&name=mydcc&version=0.0.8](https://pypi.python.org/pypi?%3Aaction=display&name=mydcc&version=0.0.8)

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [July 24, 2017, 6:54am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/16 "2017-07-24T06:54:30Z")

</div>

@jimmybow No, no sorry, I can install it. But during the last days I wasn’t much on my private machine and had not much time to test anything. I installed your package now, and had no problem installing it. But the code you posted above doesn’t work. You mind providing a minimum working example? E.g. the example from above just with your listener added? Would be really helpful, so I don’t have to figure out in a first place how your package works.  
Many thanks in advance for your effort!

---

<div class="post-metadata">

**Author:** ![jimmybow](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jimmybow/32/6281_2.png) [@jimmybow](https://community.plotly.com/u/jimmybow)\
**Post date:** [July 24, 2017, 7:45am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/17 "2017-07-24T07:45:35Z")

</div>

you can look README on my github 🙂

> **[jimmybow/mydcc](https://github.com/jimmybow/mydcc)**
>
> Contribute to mydcc development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![fkratzert](https://avatars.discourse-cdn.com/v4/letter/f/ed8c4c/32.png) [@fkratzert](https://community.plotly.com/u/fkratzert)\
**Post date:** [July 26, 2017, 7:10am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/18 "2017-07-26T07:10:58Z")

</div>

@jimmybow I finally found time to test your package. Unfortunately I have to say it performs even slower in my example from the top, then the build in Listener using 'hoverData '.

Do you get well performing results? Even your simple code example to display the mouse position as text performs not fluently, as for example with pure Javascript. I don’t think the fault is on your implementation, but in the updating of Dash/Plotly’s graph objects, but this is just guessing.

Also as a tip: In your github repository, update the code examples to “working-as-they-are” code, including all necessary imports and the app.run\_server() line. I think it would be much better for new users, who find your package, if they just could copy and paste one example to see the effect, and not copy, then figuring out all missing imports, add code lines etc.

e.g. first code example should look like:

```
import dash
import dash_core_components as dcc
import dash_html_components as html

from dash.dependencies import Output, Input

import mydcc

app = dash.Dash()

app.layout = html.Div([
    mydcc.Listener( id = "uuu", aim = 'graph' ),
    dcc.Graph( id = 'graph',
               figure = { 'data': [{'x': [1, 2, 3], 'y': [4, 1, 2]} ] }
              ),
    html.Div( id = 'text' )
])

@app.callback(
    Output('text', 'children'),
    [Input('uuu', 'data')])
def myfun(ddd):
    return str(ddd['x']) + ' and ' + str(ddd['y']) 

if __name__ == ' __main__':
    app.run_server()
```

---

<div class="post-metadata">

**Author:** ![jimmybow](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jimmybow/32/6281_2.png) [@jimmybow](https://community.plotly.com/u/jimmybow)\
**Post date:** [July 26, 2017, 12:21pm UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/19 "2017-07-26T12:21:33Z")

</div>

it should be slower than pure Javascript… 😯  
but i feel it is fluently, and the function is easy to be applied with python

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [November 16, 2017, 2:39am UTC](https://community.plotly.com/t/capturing-mouse-events-position/4616/20 "2017-11-16T02:39:56Z")

</div>

> [@fkratzert](#):
>
> There is this built-in Plotly “Toggle Spike Lines” function in each Graph, that does nearly what I want and is pretty fast, but not customizable. Let me know if I can help with some test or anything, because I can’t afford a sponsorship on my own

@fkratzert - A community PR in plotly.js has implemented this feature. There is a discussion here: [Vertical or/and horizontal line that is always shown in any hovermode · Issue #2155 · plotly/plotly.js · GitHub](https://github.com/plotly/plotly.js/issues/2155#issue-273486794). Would you mind providing your 2 cents? Thanks!

[Next page](https://community.plotly.com/t/capturing-mouse-events-position/4616.md?page=2)
