Plotly Dash回调实现JSON边界文件可视化及复选框控制
解决方案
以下是修改后的代码,实现了初始不显示任何边界文件,且支持多选边界选项展示对应区域的功能:
import dash from dash import dcc, html, Input, Output import dash_bootstrap_components as dbc import plotly.express as px import plotly.graph_objs as go import pandas as pd import geopandas as gpd import json # 读取地理数据并处理 gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) gdf_poly = gdf_poly.drop('name', axis=1) Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop=True) Eur_gdf_area = gdf_poly[gdf_poly['continent'] == 'Europe'].reset_index(drop=True) # 示例散点数据 data = pd.DataFrame({ 'Cat': ['t', 'y', 'y', 'y', 'f', 'f', 'j', 'k', 'k', 'k', 's', 's', 's', 's', 'f', 'j', 'k', 'f', 'j', 'k'], 'LAT': [5, 5, 5, 6.2, 4.3, 5.7, 14, 7, 7, 7, 7, 8.5, 19, 15, 16, 18, 17, 15, 16, 7], 'LON': [10, 10, 10, 11.1, 9.8, 11.4, 3, 3, 3, 3, 3, 8.8, 8, 15, 8, 17, 8, 6, 16, 7], }) external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP] app = dash.Dash(__name__, external_stylesheets=external_stylesheets, suppress_callback_exceptions=True) app.layout = dbc.Container([ dbc.Row([ dbc.Col([ html.Label('Cats', style={'paddingTop': '2rem', 'display': 'inline-block'}), dcc.Checklist( id='Cats', options=[ {'label': 't', 'value': 't'}, {'label': 'y', 'value': 'y'}, {'label': 'f', 'value': 'f'}, {'label': 'j', 'value': 'j'}, {'label': 'k', 'value': 'k'}, {'label': 's', 'value': 's'}, ], value=['t', 'y', 'f', 'j', 'k', 's'], ), ], width=2), dbc.Col([ html.Label('Polygon', style={'paddingTop': '1rem'}), dcc.Checklist( id='polygons', options=[ {'label': '非洲', 'value': 'Afr'}, {'label': '欧洲', 'value': 'Eur'}, ], value=[], # 初始值设为空,不显示任何边界 inline=True ), ], width=3), dbc.Col([ html.Div(dcc.Graph(id='chart', style={'height': 800})) ], width=7) ]) ], fluid=True) df = data @app.callback( Output('chart', 'figure'), [Input("Cats", "value"), Input("polygons", "value"),] ) def scatter_chart(cats, selected_polygons): # 过滤散点数据 dff = df[df['Cat'].isin(cats)] # 创建散点地图基础 fig = px.scatter_mapbox( data_frame=dff, lat='LAT', lon='LON', color='Cat', zoom=1, mapbox_style='carto-positron', ) # 构建mapbox图层列表 mapbox_layers = [] # 遍历选中的每个边界选项 for poly in selected_polygons: if poly == 'Afr': mapbox_layers.append({ "source": json.loads(Afr_gdf_area.geometry.to_json()), "below": "traces", "type": "fill", "color": "orange", "opacity": 0.1, "line": {"width": 1} }) elif poly == 'Eur': mapbox_layers.append({ "source": json.loads(Eur_gdf_area.geometry.to_json()), "below": "traces", "type": "fill", "color": "purple", "opacity": 0.1, "line": {"width": 0.2} }) # 更新地图图层 if mapbox_layers: fig.update_layout(mapbox={"layers": mapbox_layers}) else: # 如果没有选中任何边界,清空图层 fig.update_layout(mapbox={"layers": []}) return fig if __name__ == '__main__': app.run_server(debug=True, port=8052)
关键修改说明
- 初始边界状态设置:将
polygons复选框的value设为[],启动时不显示任何边界区域。 - 支持多选边界:原代码只处理单个边界的判断(
if elif),修改为遍历selected_polygons数组,为每个选中的选项添加对应图层,实现多选展示。 - 图层逻辑优化:构建
mapbox_layers列表统一管理图层,选中多个边界时会同时添加所有对应图层;未选中任何边界时清空图层。 - 布局调整:将Polygon复选框放入独立的
dbc.Col中,优化页面排版,并设置inline=True让选项横向排列。
内容的提问来源于stack exchange,提问作者Chopin
相关产品推荐
相关产品推荐

