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

如何在Streamlit-Folium中探索地图且不丢失已添加标记?

问题:Streamlit-Folium地图搜索后自定义标记消失

我用streamlit-folium在Streamlit中做地图可视化,支持用户添加自定义标记,地图设有默认起点,同时做了搜索栏让用户探索不同位置。但遇到一个问题:当搜索新位置时,之前在地图上添加的所有标记都会消失。

原始代码

import folium
import streamlit as st
from folium.plugins import Draw
from geopy.geocoders import Nominatim
from streamlit_folium import st_folium

# Default location
x, y = [41.00, 29.00]

# Search for another location
location_input = st.text_input("Search in the map")
if location_input:
    location = Nominatim(user_agent="GetLoc")
    getLocation = location.geocode(location_input)
    x, y = getLocation.latitude, getLocation.longitude

# Draw the map centered in location
m = folium.Map(location=[x,y],zoom_start=12)
Draw(
    draw_options={
        'polyline': False, 'rectangle': False, 
        'circle': False, 'polygon': False,
        'circlemarker': False
    },
    edit_options={'remove': False}
).add_to(m)
Map = st_folium(m, width = 700, height=500)

问题原因

Streamlit的运行机制是每次用户交互(比如输入搜索内容)都会重新执行整个脚本,而你之前添加的标记没有被持久化存储,脚本重新运行时生成的是全新的空白地图,自然丢失了之前的标记。

解决方案

用Streamlit的st.session_state持久化保存用户添加的标记坐标,每次生成地图时,从会话状态中取出这些坐标重新添加到地图上。修改后的代码如下:

import folium
import streamlit as st
from folium.plugins import Draw
from geopy.geocoders import Nominatim
from streamlit_folium import st_folium
from folium import Marker

# 初始化会话状态,用于保存标记坐标
if 'markers' not in st.session_state:
    st.session_state.markers = []

# 默认位置
x, y = [41.00, 29.00]

# 处理地点搜索
location_input = st.text_input("Search in the map")
if location_input:
    location = Nominatim(user_agent="GetLoc")
    getLocation = location.geocode(location_input)
    if getLocation:  # 兼容搜索不到地点的情况
        x, y = getLocation.latitude, getLocation.longitude

# 提取用户绘制的标记并保存到会话状态
map_data = st_folium(
    folium.Map(location=[x,y],zoom_start=12),
    width=700,
    height=500,
    returned_objects=['all_drawings']
)

if map_data.get('all_drawings'):
    for drawing in map_data['all_drawings']:
        # 仅处理点类型的标记
        if drawing['geometry']['type'] == 'Point':
            lat = drawing['geometry']['coordinates'][1]
            lon = drawing['geometry']['coordinates'][0]
            # 避免重复添加标记(可选)
            if [lat, lon] not in st.session_state.markers:
                st.session_state.markers.append([lat, lon])

# 重新生成地图并添加所有保存的标记
m = folium.Map(location=[x,y],zoom_start=12)
Draw(
    draw_options={
        'polyline': False, 'rectangle': False, 
        'circle': False, 'polygon': False,
        'circlemarker': False
    },
    edit_options={'remove': False}
).add_to(m)

# 从会话状态取出标记,添加到当前地图
for marker in st.session_state.markers:
    Marker(location=marker).add_to(m)

# 显示最终地图
st_folium(m, width=700, height=500, returned_objects=['all_drawings'])

关键修改说明

  • 会话状态初始化:用st.session_state.markers存储所有用户添加的标记坐标,确保页面刷新时数据不丢失。
  • 提取绘制数据:调用st_folium时指定returned_objects=['all_drawings'],获取用户在地图上绘制的所有元素。
  • 保存新标记:遍历返回的绘制数据,提取点类型的标记坐标并添加到会话状态。
  • 重新渲染标记:每次生成新地图时,从会话状态取出所有标记,重新添加到地图上。

这样无论用户搜索多少次新位置,之前添加的标记都会被保留并显示在新的地图中心位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:42:28