If I have a map with a bunch of points and connecting lines, which are generated dynamically based on input parameters - how do I respond to mouse clicks on the points and lines?
The only examples I can find require a callback referencing the specific id of a given object (like a polyline), but I want a way to capture any click and get from the context what was clicked.
Then, what you can do is to generate your own clickData in a callback. Here there is an example:
from dash import Dash, html, dcc, Input, Output
import plotly.graph_objects as go
import numpy as np
app = Dash()
# Random dataset
def generate_group_data(n_groups=3, n_points=10):
groups = []
for i in range(n_groups):
x = np.linspace(0, 10, n_points)
y = np.random.rand(n_points) + i
groups.append({
"x": x,
"y": y,
"label": f"Group {chr(65 + i)}"
})
return groups
app.layout = html.Div([
html.H3("Dynamic Lines with Click Tracking"),
html.Button("Generate New Lines", id="generate-btn", n_clicks=0),
dcc.Graph(id='my-graph'),
html.Div(id='click-output', style={'marginTop': '20px', 'fontWeight': 'bold'})
])
@app.callback(
Output('my-graph', 'figure'),
Input('generate-btn', 'n_clicks')
)
def update_figure(n_clicks):
grouped_data = generate_group_data()
fig = go.Figure()
for group in grouped_data:
fig.add_trace(go.Scatter(
x=group["x"],
y=group["y"],
name=group["label"],
mode="lines+markers",
customdata=[group["label"]] * len(group["x"]),
hoverinfo='text',
hovertext=[f"{group['label']}<br>X={x:.1f}<br>Y={y:.2f}" for x, y in zip(group["x"], group["y"])]
))
fig.update_layout(title="Click on Any Point to See Info", height=500)
return fig
@app.callback(
Output('click-output', 'children'),
Input('my-graph', 'clickData')
)
def display_click_data(clickData):
if not clickData:
return "Click on a point to see details."
point = clickData['points'][0]
trace_index = point['curveNumber']
x = point['x']
y = point['y']
group = point.get('customdata', 'Unknown')
return f"You clicked on {group} (Trace #{trace_index}) — X: {x}, Y: {y}"
if __name__ == '__main__':
app.run(debug=True)