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

Dash应用添加folium标记后地图无法加载的问题求助

问题分析与修复方案

你的代码存在几个关键错误,导致添加标记后地图无法加载:

  1. Dash无法直接渲染folium对象:布局里直接放置folium.Map(id="output-state")不符合Dash组件规则,Dash不支持直接渲染folium实例,需要将其转换为HTML组件嵌入。
  2. 参数传递错误:创建folium地图时,location=['lat', 'long']和zoom_start='zoom'用了字符串字面量,而非传入的变量lat、long、zoom,这会导致地图定位到无效坐标。
  3. 回调输出目标错误:回调输出绑定到folium.Map的children属性,但folium对象没有该属性,应该用html.Div承载生成的地图。

修复方案1:folium转HTML嵌入Dash

修改后的代码如下:

from dash import Dash, html, dcc, Input, Output, State
import folium

app = Dash()  
app.layout = html.Div([
    html.H1(id='textout'),
    # 用Div承载地图,替代直接放置folium.Map
    html.Div(id="output-state"),
    dcc.Input(id='lat', value=39.298, type='number'),
    dcc.Input(id='long', value=-76.590, type='number'),
    dcc.Input(id='zoom', value=11, type='number'),
    html.Button('Submit', id='submit-button')
])

@app.callback(Output('output-state', 'children'),
              Input('submit-button', 'n_clicks'),
              State('lat', 'value'),
              State('long', 'value'),
              State('zoom', 'value'))
def update_output(n_clicks, lat, long, zoom):
    if not n_clicks:
        # 初始状态加载默认地图
        m = folium.Map(location=[39.298, -76.590], zoom_start=11)
        folium.Marker([39.298, -76.590], popup="You Are Here!!!").add_to(m)
        # 将folium地图转为HTML字符串,嵌入iframe
        m_html = m._repr_html_()
        return html.Iframe(srcDoc=m_html, width='100%', height='600px')
    
    # 使用传入的变量创建地图,而非字符串字面量
    m = folium.Map(location=[lat, long], zoom_start=zoom)
    folium.Marker([lat, long], popup="You Are Here!!!").add_to(m)
    m_html = m._repr_html_()
    return html.Iframe(srcDoc=m_html, width='100%', height='600px')

@app.callback(Output('textout', 'children'),
              Input('submit-button', 'n_clicks'),
              State('lat', 'value'),
              State('long', 'value'),
              State('zoom', 'value'))
def update_text(n_clicks, lat, long, zoom):    
    return f'纬度 {lat}, 经度 {long}, 缩放级别 {zoom}, 点击次数 {n_clicks} 次'

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

修复方案2:直接使用dash_leaflet(更适配Dash)

既然已导入dash_leaflet,推荐用原生组件实现,避免folium转HTML的额外步骤:

import dash_leaflet as dl
from dash import Dash, html, dcc, Input, Output, State

app = Dash()  
app.layout = html.Div([
    html.H1(id='textout'),
    # 使用dash_leaflet的Map组件
    dl.Map(id="output-state", style={'width': '100%', 'height': '600px'}),
    dcc.Input(id='lat', value=39.298, type='number'),
    dcc.Input(id='long', value=-76.590, type='number'),
    dcc.Input(id='zoom', value=11, type='number'),
    html.Button('Submit', id='submit-button')
])

@app.callback(Output('output-state', 'children'),
              Input('submit-button', 'n_clicks'),
              State('lat', 'value'),
              State('long', 'value'),
              State('zoom', 'value'))
def update_output(n_clicks, lat, long, zoom):
    if not n_clicks:
        # 初始地图组件
        return [dl.TileLayer(), dl.Marker(position=[39.298, -76.590], children=dl.Popup("You Are Here!!!"))]
    
    # 更新后的地图组件
    return [
        dl.TileLayer(),
        dl.Marker(position=[lat, long], children=dl.Popup("You Are Here!!!"))
    ]

@app.callback(Output('output-state', 'center'),
              Input('submit-button', 'n_clicks'),
              State('lat', 'value'),
              State('long', 'value'))
def update_map_center(n_clicks, lat, long):
    if not n_clicks:
        return [39.298, -76.590]
    return [lat, long]

@app.callback(Output('output-state', 'zoom'),
              Input('submit-button', 'n_clicks'),
              State('zoom', 'value'))
def update_map_zoom(n_clicks, zoom):
    if not n_clicks:
        return 11
    return zoom

@app.callback(Output('textout', 'children'),
              Input('submit-button', 'n_clicks'),
              State('lat', 'value'),
              State('long', 'value'),
              State('zoom', 'value'))
def update_text(n_clicks, lat, long, zoom):    
    return f'纬度 {lat}, 经度 {long}, 缩放级别 {zoom}, 点击次数 {n_clicks} 次'

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

关键修复说明

  • 方案1通过m._repr_html_()将folium地图转为HTML字符串,再用html.Iframe嵌入Dash,解决直接渲染folium对象的问题。
  • 两种方案都修正了参数传递错误,直接使用变量而非字符串字面量。
  • 方案2采用dash_leaflet原生组件,更贴合Dash的组件逻辑,无需额外HTML转换,兼容性和性能更佳。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:23:16