如何在dash-leaflet的app.callback中配置hover_feature、click_feature的多输入输出
Dash-leaflet 多回调冲突解决方案
问题根源
冲突本质是Dash框架的核心限制:同一个组件的同一个属性,不允许被多个回调函数同时作为输出目标绑定。你原有代码中layer组件的children属性同时被点击标记回调、悬浮高亮回调两个函数绑定,因此二者无法同时生效。
最优解决方案:拆分独立图层
最简单的适配方式是将不同功能的图层拆分,分别绑定独立的输出目标,完全规避属性冲突:
第一步:修改Layout结构
把原来的单一LayerGroup拆分为两个,分别存放点击生成的标记、悬浮高亮的多边形:
app.layout = html.Div(children=[ dl.Map(children=[ dl.TileLayer(), # 拆分图层:专门存放点击生成的标记 dl.LayerGroup(id="marker-layer"), # 拆分图层:专门存放悬浮高亮的多边形 dl.LayerGroup(id="highlight-layer"), dl.GeoJSON( url='https://pkgstore.datahub.io/core/geo-countries/countries/archive/23f420f929e0e09c39d916b8aaa166fb/countries.geojson', id="countries", options=dict(style=dict(opacity=0,fillOpacity=0)), hoverStyle=arrow_function(dict(weight=2, color='red', dashArray='', opacity=1)) ) ], style={'width': '1000px', 'height': '500px'}, zoom=3, id='map'), html.Div(id='country'), html.Div(id='Country info pane') ])
第二步:调整回调绑定对应输出
将不同功能的回调输出绑定到对应的拆分图层,无需修改原有业务逻辑:
# 点击地图放置标记的回调,输出到标记专属图层 @app.callback( Output("marker-layer", "children"), Input("countries", "click_feature"), prevent_initial_call=True ) def map_click(feature): return [dl.Marker(position=[np.random.randint(-90,90),np.random.randint(-185,185)])] # 悬浮国家的回调,同时输出信息面板、高亮多边形到专属图层 @app.callback( Output('Country info pane', 'children'), Output('highlight-layer', 'children'), Input('countries', 'hover_feature'), prevent_initial_call=True ) def country_hover(feature): if feature is None: # 悬浮离开区域时清空内容 return "", [] country_id = feature['properties']['ISO_A3'] return country_id, [dl.Polygon(positions=[[30,40],[50,60]], color='#ff002d', opacity=0.2)]
备选方案:单回调多触发源
如果不想拆分图层,可以将两个触发源合并到同一个回调,通过回调上下文判断触发事件,合并输出图层内容:
# 引入回调上下文 from dash import callback_context @app.callback( Output('Country info pane', 'children'), Output('layer', 'children'), Input('countries', 'hover_feature'), Input("countries", "click_feature"), prevent_initial_call=True ) def handle_all_events(hover_feature, click_feature): # 初始化图层内容列表 layer_content = [] info_content = "" # 获取触发源 trigger = callback_context.triggered[0]['prop_id'] # 处理悬浮事件 if trigger == 'countries.hover_feature' and hover_feature is not None: info_content = hover_feature['properties']['ISO_A3'] layer_content.append(dl.Polygon(positions=[[30,40],[50,60]], color='#ff002d', opacity=0.2)) # 处理点击事件 if trigger == 'countries.click_feature': layer_content.append(dl.Marker(position=[np.random.randint(-90,90),np.random.randint(-185,185)])) return info_content, layer_content
内容的提问来源于stack exchange,提问作者user8849845
相关产品推荐
相关产品推荐

