Add marker after clicking on map

Hi community, a suggestion, there is a basic tutorial missing, how to add a marker to a click on a map event. I have been struggling with this and I cannot find it anywhere. I am still struggling a lot with session state, and I know I am not the only one as I found a person with the exact same problem. Here is what I managed to do, but I have to click two times on the map to get the marker there:

the idea: display a marker on the map once the user clicks on the map

expected behaviour: marker appears where the user clicked, if the user clicks somewhere else, the marker appears over the new click

actual behaviour: user clicks once on the map and nothing happens, then clicks again and marker appears over the previous click, not the last

    if 'center' not in st.session_state:
        st.session_state.center = [46.903354, 1.888334]
    # Initialize session state to store clicked points
    if 'location' not in st.session_state:
        st.session_state.location = folium.Marker(st.session_state.center)

    # Create a Folium map
    m = folium.Map(location=[46.903354, 1.888334], zoom_start=6)
    fg = folium.FeatureGroup(name="Markers")
    fg.add_child(st.session_state.location)

    # When the user interacts with the map
    map_state_change = st_folium(
        m,
        feature_group_to_add=fg,
        width=620, height=580,
        returned_objects=['last_clicked'],
        key="folium_map"
    )

    if map_state_change['last_clicked']:
        loc = map_state_change['last_clicked']
        st.session_state.location = folium.Marker([loc['lat'], loc['lng']])
        fg.clear_layers()  # Clear existing markers
        fg.add_child(st.session_state.location)  # Add the new marker
        folium_static(m)

if anyone could point me to a tutorial or indicate how to fix the issue I would really appreciate! thanks!

I managed to add a marker to each click but I have no idea how to make the previous marker dissapear…

    import streamlit as st
    import folium
    from streamlit_folium import folium_static

    def get_pos(lat, lng):
        return lat, lng

    # Create a Folium map
    m = folium.Map(location=[46.903354, 1.888334], zoom_start=6)
    m.add_child(folium.ClickForMarker())

    # When the user interacts with the map
    map = st_folium(
        m,
        width=620, height=580,
        key="folium_map"
    )
    data = None
    if map.get("last_clicked"):
        data = get_pos(map["last_clicked"]["lat"], map["last_clicked"]["lng"])

    if data is not None:
        st.write(data)

Also was looking for same solution, finally made it.
Here is the code, which worked for me.

import streamlit as st
import folium
from streamlit_folium import st_folium

# Function to get position from click coordinates
def get_pos(lat, lng):
    return lat, lng

# Initialize session state to store marker location
if "marker_location" not in st.session_state:
    st.session_state.marker_location = [43.238949, 76.889709]  # Default location
    st.session_state.zoom = 11  # Default zoom

# Create the base map
m = folium.Map(location=st.session_state.marker_location, zoom_start=st.session_state.zoom)

# Add a marker at the current location in session state
marker = folium.Marker(
    location=st.session_state.marker_location,
    draggable=False
)
marker.add_to(m)

# Render the map and capture clicks
map = st_folium(m, width=620, height=580, key="folium_map")

# Update marker position immediately after each click
if map.get("last_clicked"):
    lat, lng = map["last_clicked"]["lat"], map["last_clicked"]["lng"]
    st.session_state.marker_location = [lat, lng]  # Update session state with new marker location
    st.session_state.zoom = map["zoom"]
    # Redraw the map immediately with the new marker location
    m = folium.Map(location=st.session_state.marker_location, zoom_start=st.session_state.zoom)
    folium.Marker(
        location=st.session_state.marker_location,
        draggable=False
    ).add_to(m)
    map = st_folium(m, width=620, height=580, key="folium_map")

# Display coordinates
st.write(f"Coordinates: {st.session_state.marker_location}")

1 Like