Clickable scatter plot looses interactivity on mouse movement

Hi, I am new to Streamlit, and I am trying to make an interactive scatter plot where you can click to select a datapoint from a plot, and then click again to de-select it. And I want this to happen without re-drawing the whole plot (without flickering on the screen).

Problem is that whenever I move the mouse, the plot loses its clickability.

2024-07-18 16-38-29 - Trim

  1. You can see that on the first click, It re-draws the whole thing, and screen flickers, which is not intended, but ok.
  2. For the next 4 clicks, it works normally. Every time I click, it selects it and changes color without re-drawing the whole thing.
  3. But after I move the mouse, I try clicking, and it wouldn’t change color.

I have attached my code below.

I was wondering if anybody can help me fix the issue where it loses its clickability after mouse movement, and if there is a better way to make a interactive and clickable scatterplot other then plotly. Thank you.

Note: There is only one data point for now, for debugging purpose. It should work for multiple points

import streamlit as st
import plotly.graph_objects as go
from streamlit_plotly_events import plotly_events
import streamlit.components.v1 as components

# Initialize session state
if 'selected' not in st.session_state:
    st.session_state.selected = False

# Create the plot
def create_plot():
    fig = go.Figure()
    
    # Add the single datapoint
    fig.add_trace(go.Scatter(
        x=[1], 
        y=[1], 
        mode='markers',
        marker=dict(
            size=20,
            color='blue' if st.session_state.selected else 'lightblue',
        ),
        name='Datapoint'
    ))
    
    # Set layout
    fig.update_layout(
        title='Interactive Plot',
        xaxis_title='X Axis',
        yaxis_title='Y Axis',
        uirevision='constant'
    )
    fig['layout']['uirevision'] = True
    
    return fig

# Initialize plot
if 'fig' not in st.session_state:
    st.session_state.fig = create_plot()

# Create a placeholder for the plot
plot_placeholder = st.empty()

with plot_placeholder.container():
    selected_points = plotly_events(
        st.session_state.fig,
        click_event=True,
        override_height="400px",
        key='interactive_plot'
    )


# Handle selection
if selected_points:
    st.session_state.selected = not st.session_state.selected
    st.session_state.fig.data[0].marker.color = 'blue' if st.session_state.selected else 'lightblue'

    with plot_placeholder.container():
        plotly_events(
            st.session_state.fig,
            click_event=True,
            override_height="400px",
            key='interactive_plots'
        )


# Display selection state
st.write(f"Point selected: {st.session_state.selected}")

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.