You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python Dash/Plotly中实现类似Matlab Datatip的功能?

Solution for Interactive Annotations in Plotly Dash (and Your Earlier Plotly Python Questions)

Hey Nate, let's work through your problem step by step based on your updates!

Jan 20th: Plotly Python Datatip-like Functionality

I totally get the frustration here—trying to replicate Matlab's Datatip in Plotly Offline can feel like hitting a wall since the mouse event documentation is pretty sparse. The Plotly.js examples you found are exactly what you need for this kind of interaction, but Plotly Offline (the plotly.offline.plot() approach) doesn't support interactive callbacks directly. That's where Dash comes in, and it's great you already shifted direction to that tool later on.

Your sample code creates a static offline plot, but to add click-triggered interactions, you'd need to move to a Dash app. The graph_widget module has basic event handling, but it's nowhere near as flexible as Dash for building interactive tools. Let's jump straight to the Dash solution since that's where you landed!

Jan 27th: Adding Clickable Annotations in Python Dash

Great call going with Dash—it's made for building interactive Plotly apps like this. Below is a complete example that combines a scatter plot with dynamic annotations when you click data points, matching the "annotations example + styling" you referenced:

import dash
from dash import dcc, html, Input, Output, State
import plotly.graph_objs as go
import numpy as np

# Initialize the Dash app
app = dash.Dash(__name__)

# Create random data (matching your original sample)
N = 1000
random_x = np.random.randn(N)
random_y = np.random.randn(N)

# Initial figure setup with empty annotations
initial_figure = go.Figure(
    data=[go.Scatter(
        x=random_x,
        y=random_y,
        mode='markers',
        marker=dict(size=8, color='royalblue')
    )],
    layout=go.Layout(
        title='Click a Point to Add a Datatip Annotation',
        xaxis=dict(title='Random X Values'),
        yaxis=dict(title='Random Y Values'),
        annotations=[],
        hovermode='closest'  # Optional: Shows basic hover text by default
    )
)

# App layout
app.layout = html.Div([
    dcc.Graph(
        id='scatter-graph',
        figure=initial_figure
    ),
    # Optional button to clear all annotations
    html.Button('Clear All Annotations', id='clear-btn', n_clicks=0, style={'margin-top': '10px'})
])

# Callback to handle clicks and clear button
@app.callback(
    Output('scatter-graph', 'figure'),
    Input('scatter-graph', 'clickData'),
    Input('clear-btn', 'n_clicks'),
    State('scatter-graph', 'figure')
)
def update_annotations(click_data, n_clicks, current_figure):
    # Check which component triggered the callback
    ctx = dash.callback_context
    triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
    
    # Clear annotations if button was clicked
    if triggered_id == 'clear-btn':
        current_figure['layout']['annotations'] = []
        return current_figure
    
    # Add annotation if a point was clicked
    if click_data is not None:
        point = click_data['points'][0]
        x_val = point['x']
        y_val = point['y']
        
        # Create a polished datatip-style annotation
        new_annotation = dict(
            x=x_val,
            y=y_val,
            text=f'X: {x_val:.2f}<br>Y: {y_val:.2f}',
            showarrow=True,
            arrowhead=2,
            ax=30,
            ay=-30,
            bgcolor='rgba(255, 255, 255, 0.95)',
            bordercolor='#333',
            borderwidth=1,
            font=dict(size=12)
        )
        
        # Append the new annotation to existing ones
        current_figure['layout']['annotations'].append(new_annotation)
    
    return current_figure

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

Key Details About This Implementation:

  • Dynamic Annotations: Every time you click a scatter point, a formatted annotation with the point's exact X/Y values is added to the plot.
  • Annotation Styling: The annotation uses a semi-transparent background, border, and offset arrow to mimic Matlab's Datatip look.
  • Clear Functionality: The optional button lets you reset all annotations with one click if you need to start fresh.
  • Hover Fallback: The hovermode='closest' adds basic hover text as a backup, but the click-triggered annotations are the main feature.

Just run this script, and you'll get a local web app where clicking any scatter point adds the exact dynamic annotation you wanted!

内容的提问来源于stack exchange,提问作者Nate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:47:30