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

通过回调向Dash Leaflet地图添加新多边形的问题求助

问题分析与解决方案

你的代码核心问题有两个:

  1. 合并几何时没有构建正确的GeoDataFrame结构,导致生成的GeoJSON无法被Dash Leaflet正确解析;
  2. 返回的是JSON字符串而非Python字典,不符合dl.GeoJSON组件data属性的要求。

以下是修正后的完整代码,附带关键修改说明:

import pandas as pd
import json
from dash import Dash, dcc, html, Input, Output, State
import dash_leaflet as dl
import geopandas as gpd

lat1, lon1 = 36.215487, -81.674006

app = Dash()

input_details = html.Div([
    html.Div([
        html.Div(['Buffer Distance'], style={'width': '37%', 'display': 'inline-block'}),
        dcc.Input(
            value=100,
            id="buffer-distance",
            type='number',
            placeholder='Required',
        ),
    ]),
])

default_map_children = [
    dl.TileLayer(),
    dl.FeatureGroup([
        dl.EditControl(id="edit_control"),
    ]),
    dl.GeoJSON(id='map-geojsons', style={"color": "#ff0000", "weight": 2})  # 自定义样式区分图形
]

map_input_results_tab = html.Div(
    [
        html.H2('Add Shapes to Map an Area of Interest'),
        dl.Map(
            id='leaflet-map',
            style={'width': '100%', 'height': '50vh'},
            center=[lat1, lon1],
            zoom=16,
            children=default_map_children
        )
    ])

app.layout = html.Div([input_details, map_input_results_tab])


@app.callback(
    Output('map-geojsons', 'data'),
    Input('edit_control', 'geojson'),
    State('buffer-distance', 'value'),
    prevent_initial_call=True  # 防止初始空值触发回调
)
def update_estimates(drawn_geojson, perim_clear):
    if not drawn_geojson.get("features") or perim_clear is None:
        return None

    # 加载绘制的GeoJSON为GeoDataFrame
    gdf = gpd.GeoDataFrame.from_features(drawn_geojson["features"])
    gdf = gdf.set_crs(crs=4326)
    utm_crs = gdf.estimate_utm_crs()
    if utm_crs is None:
        # 无法估算UTM坐标系时直接返回原图形
        return drawn_geojson
    gdf_utm = gdf.to_crs(crs=utm_crs)

    # 生成缓冲后的几何,过滤空几何(避免缓冲距离过大导致图形消失)
    buffered_gdf = gdf_utm.copy()
    buffered_gdf['geometry'] = buffered_gdf['geometry'].buffer(-perim_clear)
    buffered_gdf = buffered_gdf[~buffered_gdf['geometry'].is_empty]

    # 合并原图形和缓冲后的图形,转回WGS84坐标系
    combine_gdf = pd.concat([gdf_utm, buffered_gdf], ignore_index=True).to_crs(crs=4326)

    # 将GeoDataFrame转为Python字典(而非JSON字符串)返回
    return json.loads(combine_gdf.to_json())


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

关键修改点说明:

  • 修正GeoDataFrame合并逻辑:不再直接合并几何Series,而是复制原GeoDataFrame并替换几何列,确保每个图形都是独立的Feature;
  • JSON格式转换:使用json.loads()将GeoJSON字符串转为Python字典,符合dl.GeoJSON组件的数据要求;
  • 空几何过滤:添加buffered_gdf = buffered_gdf[~buffered_gdf['geometry'].is_empty],避免缓冲距离过大导致的无效几何;
  • UTM坐标系校验:增加对estimate_utm_crs()返回值的判断,防止无法估算坐标系时出错;
  • 回调优化:添加prevent_initial_call=True,避免应用启动时的空值触发回调;
  • 样式自定义:给dl.GeoJSON添加默认样式,方便区分原图形和缓冲后的图形。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 00:07:20