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

如何在Dash中基于用户选择为GeoJSON地图区域着色

问题

开发Dash应用展示美国地图,希望点击州后将选中的州标红。当前点击州能在页面显示,但着色回调会改变整个地图颜色而非仅选中区域,附上示例代码,求解决方法。

解决方案

问题出在样式匹配逻辑、默认样式缺失及选中状态存储方式上,修改以下几点即可实现需求:

  • 属性名匹配修正:GeoJSON中州名的属性是NAME(大写),原代码用name(小写)导致匹配失败。
  • 添加默认样式:样式函数需返回未选中区域的默认样式,否则未匹配的区域会丢失样式导致地图整体变色。
  • 支持多选状态存储:将hideout改为存储选中州名列表,而非单个feature,实现点击切换选中/取消选中并标记对应区域。

修改后完整代码

import json
import dash
from dash import html, Dash, Input, State, Output
import dash_leaflet as dl
import geopandas as gpd
from dash import dash_table
from dash_extensions.javascript import assign

# 读取美国州GeoJSON数据
us_states_gdf = gpd.read_file("us_states.geojson")
us_states_geojson = json.loads(us_states_gdf.to_json())

# 自定义样式函数:选中州标红,其余保持默认样式
style_handle = assign("""function(feature, context){
    const selectedStates = context.props.hideout?.selectedStates || [];
    // 匹配州名,选中则标红
    if(selectedStates.includes(feature.properties.NAME)){
        return {color: '#ff0000', weight: 2};
    }
    // 返回未选中区域的默认样式
    return {color: '#3388ff', weight: 1};
}""")

app = Dash(__name__)
app.layout = html.Div([
    dl.Map([
        dl.TileLayer(url="http://tile.stamen.com/toner-lite/{z}/{x}/{y}.png"),
        dl.GeoJSON(
            data=us_states_geojson, 
            id="state-layer",
            options=dict(style=style_handle), 
            hideout=dict(selectedStates=[])  # 存储选中州名列表
        )],
        style={'width': '100%', 'height': '250px'},
        id="map",
        center=[39.8283, -98.5795],
    ),
    html.Div(id='state-container', children=[]),
    dash_table.DataTable(
        id='state-table', 
        columns=[{"name": "州名", "id": "state"}], 
        data=[]
    )
])

# 更新选中州列表到hideout
app.clientside_callback(
    """
    function(clickFeature, currentSelected) {
        if(!clickFeature){
            return window.dash_clientside.no_update;
        }
        const stateName = clickFeature.properties.NAME;
        let newSelected = [...currentSelected];
        // 切换选中状态:已选中则移除,未选中则添加
        if(newSelected.includes(stateName)){
            newSelected = newSelected.filter(name => name !== stateName);
        }else{
            newSelected.push(stateName);
        }
        return {selectedStates: newSelected};
    }
    """,
    Output("state-layer", "hideout"),
    Input("state-layer", "click_feature"),
    State("state-layer", "hideout"),
)

# 更新选中状态展示(表格和文本)
app.clientside_callback(
    """
    function(hideout) {
        const selectedStates = hideout?.selectedStates || [];
        // 转换为表格数据格式
        const tableData = selectedStates.map(state => ({state: state}));
        // 生成显示文本
        const displayText = selectedStates.length > 0 
            ? `已选中州:${selectedStates.join(', ')}` 
            : '未选中任何州';
        return [tableData, displayText];
    }
    """,
    Output("state-table", "data"),
    Output("state-container", "children"),
    Input("state-layer", "hideout"),
)

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

关键修改说明

  1. 样式函数:修正属性名匹配为feature.properties.NAME,添加默认样式返回,确保未选中区域正常显示;选中区域设置红色边框(可根据需求调整color和weight)。
  2. Hideout存储:改为存储选中州名列表,支持多选中切换。
  3. 回调逻辑:点击州时切换该州的选中状态,同步更新hideout和页面展示内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:57:33