Files
gh-k-dense-ai-claude-scient…/skills/plotly/reference/export-interactivity.md
2025-11-30 08:30:10 +08:00

9.0 KiB

Export and Interactivity

Static Image Export

Installation

Static image export requires Kaleido:

uv pip install kaleido

Kaleido v1+ requires Chrome/Chromium on your system.

Supported Formats

  • Raster: PNG, JPEG, WebP
  • Vector: SVG, PDF

Writing to File

import plotly.express as px

fig = px.scatter(df, x='x', y='y')

# Format inferred from extension
fig.write_image('chart.png')
fig.write_image('chart.pdf')
fig.write_image('chart.svg')

# Explicit format
fig.write_image('chart', format='png')

Converting to Bytes

# Get image as bytes
img_bytes = fig.to_image(format='png')

# Display in Jupyter
from IPython.display import Image
Image(img_bytes)

# Save to file manually
with open('chart.png', 'wb') as f:
    f.write(img_bytes)

Customizing Export

fig.write_image(
    'chart.png',
    format='png',
    width=1200,
    height=800,
    scale=2  # Higher resolution
)

Setting Export Defaults

import plotly.io as pio

pio.kaleido.scope.default_format = 'png'
pio.kaleido.scope.default_width = 800
pio.kaleido.scope.default_height = 600
pio.kaleido.scope.default_scale = 2

Exporting Multiple Figures

import plotly.io as pio

# Kaleido v1+ only
pio.write_images(
    fig=[fig1, fig2, fig3],
    file=['chart1.png', 'chart2.png', 'chart3.png']
)

Interactive HTML Export

Basic Export

# Full standalone HTML
fig.write_html('interactive_chart.html')

# Open in browser
fig.show()

File Size Control

# Full library embedded (~5MB file)
fig.write_html('chart.html', include_plotlyjs=True)

# CDN reference (~2KB file, requires internet)
fig.write_html('chart.html', include_plotlyjs='cdn')

# Local reference (requires plotly.min.js in same directory)
fig.write_html('chart.html', include_plotlyjs='directory')

# No library (for embedding in existing HTML with Plotly.js)
fig.write_html('chart.html', include_plotlyjs=False)

HTML Configuration

fig.write_html(
    'chart.html',
    config={
        'displayModeBar': True,
        'displaylogo': False,
        'toImageButtonOptions': {
            'format': 'png',
            'filename': 'custom_image',
            'height': 800,
            'width': 1200,
            'scale': 2
        }
    }
)

Embedding in Templates

# Get only the div (no full HTML structure)
html_div = fig.to_html(
    full_html=False,
    include_plotlyjs='cdn',
    div_id='my-plot'
)

# Use in Jinja2 template
template = """
<html>
<body>
    <h1>My Dashboard</h1>
    {{ plot_div | safe }}
</body>
</html>
"""

Interactivity Features

Built-in Interactions

Plotly figures automatically support:

  • Hover tooltips - Display data on hover
  • Pan and zoom - Click and drag to pan, scroll to zoom
  • Box/lasso select - Select multiple points
  • Legend toggling - Click to hide/show traces
  • Double-click - Reset axes

Hover Customization

# Hover mode
fig.update_layout(
    hovermode='closest'  # 'x', 'y', 'closest', 'x unified', False
)

# Custom hover template
fig.update_traces(
    hovertemplate='<b>%{x}</b><br>' +
                  'Value: %{y:.2f}<br>' +
                  'Extra: %{customdata[0]}<br>' +
                  '<extra></extra>'
)

# Hover data in Plotly Express
fig = px.scatter(
    df, x='x', y='y',
    hover_data={
        'extra_col': True,     # Show column
        'x': ':.2f',           # Format column
        'hidden': False        # Hide column
    },
    hover_name='name_column'   # Bold title
)

Click Events (Dash/FigureWidget)

For web applications, use Dash or FigureWidget for click handling:

# With FigureWidget in Jupyter
import plotly.graph_objects as go

fig = go.FigureWidget(data=[go.Scatter(x=[1, 2, 3], y=[4, 5, 6])])

def on_click(trace, points, selector):
    print(f'Clicked on points: {points.point_inds}')

fig.data[0].on_click(on_click)
fig

Zoom and Pan

# Disable zoom/pan
fig.update_xaxes(fixedrange=True)
fig.update_yaxes(fixedrange=True)

# Set initial zoom
fig.update_xaxes(range=[0, 10])
fig.update_yaxes(range=[0, 100])

# Constrain zoom
fig.update_xaxes(
    range=[0, 10],
    constrain='domain'
)

Rangeslider (Time Series)

fig = px.line(df, x='date', y='value')

# Add rangeslider
fig.update_xaxes(rangeslider_visible=True)

# Customize rangeslider
fig.update_xaxes(
    rangeslider=dict(
        visible=True,
        thickness=0.05,
        bgcolor='lightgray'
    )
)

Range Selector Buttons

fig.update_xaxes(
    rangeselector=dict(
        buttons=list([
            dict(count=1, label='1m', step='month', stepmode='backward'),
            dict(count=6, label='6m', step='month', stepmode='backward'),
            dict(count=1, label='YTD', step='year', stepmode='todate'),
            dict(count=1, label='1y', step='year', stepmode='backward'),
            dict(step='all', label='All')
        ]),
        x=0.0,
        y=1.0,
        xanchor='left',
        yanchor='top'
    )
)

Buttons and Dropdowns

fig.update_layout(
    updatemenus=[
        dict(
            type='buttons',
            direction='left',
            buttons=list([
                dict(
                    args=[{'type': 'scatter'}],
                    label='Scatter',
                    method='restyle'
                ),
                dict(
                    args=[{'type': 'bar'}],
                    label='Bar',
                    method='restyle'
                )
            ]),
            x=0.1,
            y=1.15
        )
    ]
)

Sliders

fig.update_layout(
    sliders=[
        dict(
            active=0,
            steps=[
                dict(
                    method='update',
                    args=[{'visible': [True, False]},
                          {'title': 'Dataset 1'}],
                    label='Dataset 1'
                ),
                dict(
                    method='update',
                    args=[{'visible': [False, True]},
                          {'title': 'Dataset 2'}],
                    label='Dataset 2'
                )
            ],
            x=0.1,
            y=0,
            len=0.9
        )
    ]
)

Animations

Using Plotly Express

fig = px.scatter(
    df, x='gdp', y='life_exp',
    animation_frame='year',     # Animate over this column
    animation_group='country',  # Group animated elements
    size='population',
    color='continent',
    hover_name='country',
    log_x=True,
    range_x=[100, 100000],
    range_y=[25, 90]
)

# Customize animation speed
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 1000
fig.layout.updatemenus[0].buttons[0].args[1]['transition']['duration'] = 500

Using Graph Objects

import plotly.graph_objects as go

fig = go.Figure(
    data=[go.Scatter(x=[1, 2], y=[1, 2])],
    layout=go.Layout(
        updatemenus=[dict(
            type='buttons',
            buttons=[dict(label='Play',
                         method='animate',
                         args=[None])]
        )]
    ),
    frames=[
        go.Frame(data=[go.Scatter(x=[1, 2], y=[1, 2])]),
        go.Frame(data=[go.Scatter(x=[1, 2], y=[2, 3])]),
        go.Frame(data=[go.Scatter(x=[1, 2], y=[3, 4])])
    ]
)

Displaying Figures

In Jupyter

# Default renderer
fig.show()

# Specific renderer
fig.show(renderer='notebook')  # or 'jupyterlab', 'colab', 'kaggle'

In Web Browser

fig.show()  # Opens in default browser

In Dash Applications

import dash
from dash import dcc, html
import plotly.express as px

app = dash.Dash(__name__)

fig = px.scatter(df, x='x', y='y')

app.layout = html.Div([
    dcc.Graph(figure=fig)
])

app.run_server(debug=True)

Saving and Loading

# Save as JSON
fig.write_json('figure.json')

# Load from JSON
import plotly.io as pio
fig = pio.read_json('figure.json')

# Save as HTML
fig.write_html('figure.html')

Configuration Options

Display Config

config = {
    'displayModeBar': True,      # Show toolbar
    'displaylogo': False,        # Hide Plotly logo
    'modeBarButtonsToRemove': ['pan2d', 'lasso2d'],  # Remove buttons
    'toImageButtonOptions': {
        'format': 'png',
        'filename': 'custom_image',
        'height': 500,
        'width': 700,
        'scale': 1
    },
    'scrollZoom': True,          # Enable scroll zoom
    'editable': True,            # Enable editing
    'responsive': True           # Responsive sizing
}

fig.show(config=config)
fig.write_html('chart.html', config=config)

Available Config Options

  • displayModeBar: Show/hide toolbar ('hover', True, False)
  • displaylogo: Show Plotly logo
  • modeBarButtonsToRemove: List of buttons to hide
  • modeBarButtonsToAdd: Custom buttons
  • scrollZoom: Enable scroll to zoom
  • doubleClick: Double-click behavior ('reset', 'autosize', 'reset+autosize', False)
  • showAxisDragHandles: Show axis drag handles
  • editable: Allow editing
  • responsive: Responsive sizing