24

Plotly allows you to display text fields when hovering over a point on a scatterplot. Is it possible to instead display an image associated with each point when the user hovers over or clicks on it? I am mostly just using the web interface, but I could instead push my ggplot from R.

MLavoie
  • 9,671
  • 41
  • 36
  • 56
half-pass
  • 1,851
  • 4
  • 22
  • 33

2 Answers2

15

Unfortunately, there is no easy way to display images on hover on plotly graphs at the moment.

If you are willing to learn some javascript, plotly's embed API allows you to customize hover (as well as click) interactivity.

Here is an example of a custom hover interaction showing images on top of a plotly graph. The javascript source code can be found here.

etpinard
  • 4,756
  • 1
  • 20
  • 26
5

Images on hover is now available by Plotly lib. Here is a sample:

enter image description here

from dash import Dash, dcc, html, Input, Output, no_update
import plotly.graph_objects as go
import pandas as pd

# Small molcule drugbank dataset
# Source: https://raw.githubusercontent.com/plotly/dash-sample-apps/main/apps/dash-drug-discovery/data/small_molecule_drugbank.csv'
data_path = 'datasets/small_molecule_drugbank.csv'

df = pd.read_csv(data_path, header=0, index_col=0)

fig = go.Figure(data=[
    go.Scatter(
        x=df["LOGP"],
        y=df["PKA"],
        mode="markers",
        marker=dict(
            colorscale='viridis',
            color=df["MW"],
            size=df["MW"],
            colorbar={"title": "Molecular<br>Weight"},
            line={"color": "#444"},
            reversescale=True,
            sizeref=45,
            sizemode="diameter",
            opacity=0.8,
        )
    )
])

# turn off native plotly.js hover effects - make sure to use
# hoverinfo="none" rather than "skip" which also halts events.
fig.update_traces(hoverinfo="none", hovertemplate=None)

fig.update_layout(
    xaxis=dict(title='Log P'),
    yaxis=dict(title='pkA'),
    plot_bgcolor='rgba(255,255,255,0.1)'
)

app = Dash(__name__)

app.layout = html.Div([
    dcc.Graph(id="graph-basic-2", figure=fig, clear_on_unhover=True),
    dcc.Tooltip(id="graph-tooltip"),
])


@app.callback(
    Output("graph-tooltip", "show"),
    Output("graph-tooltip", "bbox"),
    Output("graph-tooltip", "children"),
    Input("graph-basic-2", "hoverData"),
)
def display_hover(hoverData):
    if hoverData is None:
        return False, no_update, no_update

    # demo only shows the first point, but other points may also be available
    pt = hoverData["points"][0]
    bbox = pt["bbox"]
    num = pt["pointNumber"]

    df_row = df.iloc[num]
    img_src = df_row['IMG_URL']
    name = df_row['NAME']
    form = df_row['FORM']
    desc = df_row['DESC']
    if len(desc) > 300:
        desc = desc[:100] + '...'

    children = [
        html.Div([
            html.Img(src=img_src, style={"width": "100%"}),
            html.H2(f"{name}", style={"color": "darkblue"}),
            html.P(f"{form}"),
            html.P(f"{desc}"),
        ], style={'width': '200px', 'white-space': 'normal'})
    ]

    return True, bbox, children


if __name__ == "__main__":
    app.run_server(debug=True)

More info: https://dash.plotly.com/dash-core-components/tooltip

Cassio Seffrin
  • 7,293
  • 1
  • 54
  • 54
  • Is it safe to say the that your approach only loads and shows the images on the `on hover` event, while using purely a [Adavance Hover Template](https://plotly.com/python/hover-text-and-formatting/#advanced-hover-template) would load all images to then show `on hover`? – Eduardo Reis Apr 19 '22 at 17:02
  • @EduardoReis using the customs callbacks to display images will only get the REST image when the mouse is over the graphic node. I will suggest you to test advance hover template in debug mode to check if it will load all the images. It don't seems to be a good approach to get all the images, I never put it to prove. When you get this answer may you could share the results with community – Cassio Seffrin Apr 19 '22 at 18:16