如何为Folium地图GeoJson多边形添加Plotly图表弹窗?
问题描述
我有一个包含多要素的GeoJSON文件,已在Folium交互式地图上展示多边形。每个城市对应的Plotly图表存储在当前工作目录的graphs/CityName.HTML路径下。目前可实现多边形的悬停或点击弹窗,但无法将Plotly图表以HTML字符串形式添加到GeoJSON弹窗中。曾尝试给Marker添加弹窗但未成功,希望通过循环遍历GeoJSON要素,为每个多边形添加对应图表的弹窗。现有代码片段如下:
import folium import geopandas as gpd import codecs map = folium.Map(location=['51.096246199999996', '4.178629103169916'], tiles="cartodbpositron", zoom_start=9) geojson_file_df = gpd.read_file('Refgem_geojson.json') loc = 'Project GEO ICT' title_html = ''' <h3 align="center" style="font-size:20px"><b>{}</b></h3> '''.format(loc) map.get_root().html.add_child(folium.Element(title_html)) g_map = folium.GeoJson( geojson_file, name="GeoJson", style_function=lambda x: {'fillColor': 'orange'} ).add_to(map) folium.GeoJsonTooltip( fields=['NISCODE','NAAM', 'OPPERVL'], aliases=['NISCODE', 'Naam', 'Oppervlakte'], sticky=False ).add_to(g_map) folium.GeoJsonPopup( fields=["NAAM", "Average Prices: " ,"Woonhuis", "Villa", "Studio"], aliases=["Naam", "Average Prices: ","Woonhuis", "Villa", "Studio"] ).add_to(g_map) html=""" <iframe src="""" + codecs.open("graphs/AARTSELAAR.html", 'r').read() + """" width="850" height="400" frameborder="0"> """ popup1 = folium.Popup(folium.Html(html, script=True)) folium.Marker(['51.096246199999996','4.178629103169916'],popup=popup1,icon=folium.Icon( icon='home', prefix='fa')).add_to(map) map
解决方案
核心是利用folium.GeoJson的popup参数绑定自定义函数,动态读取对应城市的Plotly图表HTML文件,生成专属弹窗。替代原有的GeoJsonPopup(仅支持绑定GeoJSON属性字段),实现图表嵌入。
修改后的完整代码
import folium import geopandas as gpd import codecs from folium import Html, Popup # 初始化地图,避免变量名与内置函数冲突 m = folium.Map(location=['51.096246199999996', '4.178629103169916'], tiles="cartodbpositron", zoom_start=9) # 添加地图标题 loc = 'Project GEO ICT' title_html = ''' <h3 align="center" style="font-size:20px"><b>{}</b></h3> '''.format(loc) m.get_root().html.add_child(folium.Element(title_html)) # 读取GeoJSON数据 geojson_data = gpd.read_file('Refgem_geojson.json') # 定义弹窗生成函数:根据GeoJSON要素属性加载对应城市的图表 def generate_city_popup(feature): city_name = feature['properties']['NAAM'] graph_file_path = f"graphs/{city_name}.html" try: # 读取Plotly图表的HTML内容 with codecs.open(graph_file_path, 'r', encoding='utf-8') as file: graph_html_content = file.read() # 构建包含城市名和图表的弹窗HTML popup_html = Html(f""" <h4 style="margin:0 0 10px 0;">{city_name}</h4> <div style="width:800px; height:400px; overflow:auto;">{graph_html_content}</div> """, script=True) # 返回带内容的弹窗,设置最大宽度 return Popup(popup_html, max_width=850) except FileNotFoundError: # 若图表文件不存在,返回提示弹窗 return Popup(Html(f"<h4>{city_name}</h4><p>暂无可用图表数据</p>", script=True)) # 添加GeoJSON图层,绑定自定义弹窗生成函数 folium.GeoJson( geojson_data, name="GeoJson", style_function=lambda x: {'fillColor': 'orange'}, popup=generate_city_popup # 关键:绑定动态弹窗函数 ).add_to(m) # 保留原有悬停提示框 folium.GeoJsonTooltip( fields=['NISCODE','NAAM', 'OPPERVL'], aliases=['NISCODE', 'Naam', 'Oppervlakte'], sticky=False ).add_to(m) # 保存地图到本地(可选) m.save('city_map_with_graphs.html') # 显示地图 m
关键说明
- 变量名修正:将原
map变量改为m,避免与Python内置函数冲突。 - 动态弹窗函数:
generate_city_popup从GeoJSON要素中提取城市名,拼接图表文件路径,读取HTML内容后直接嵌入弹窗(替代原iframe方式,避免路径/跨域问题)。 - 异常处理:针对图表文件缺失的情况,返回友好提示弹窗,保证程序稳定运行。
- 移除冗余组件:删除原
GeoJsonPopup和测试用Marker,避免弹窗冲突。
内容的提问来源于stack exchange,提问作者Stewie
相关产品推荐
相关产品推荐

