如何修改Folium地图代码实现鼠标悬停时右上角展示信息?
Folium地图悬停固定区域信息展示问题
我使用如下代码,基于美国地理数据完成了各行政区域的标记展示(因工作相关数据无法对外展示,故以美国公开数据作为示例):
import dload from shapely.geometry import shape import geopandas as gpd import pandas as pd import folium json_string = 'https://raw.githubusercontent.com/datasets/geo-admin1-us/master/data/admin1-us.geojson' j = dload.json(json_string) gdf_usa = gpd.GeoDataFrame.from_features(j["features"]) gdf_usa.head() gdf_usa_new = gpd.GeoDataFrame(gdf_usa, crs="EPSG:4326", geometry='geometry') usa_map = gdf_usa_new.explore(tiles='CartoDB positron') usa_map gdf_usa_new["long"] = gdf_usa_new.to_crs(epsg='4326').centroid.map(lambda p: p.x) gdf_usa_new["lat"] = gdf_usa_new.to_crs(epsg='4326').centroid.map(lambda p: p.y) for i in range(0,len(gdf_usa_new)): folium.Marker( location=[gdf_usa_new.iloc[i]['lat'], gdf_usa_new.iloc[i]['long']], popup=gdf_usa_new.iloc[i]['name'], icon=folium.DivIcon(html=f"""<div style="font-family: courier new; color: white">{gdf_usa_new.iloc[i]['name']}</div>""") ).add_to(usa_map) usa_map
- 当前运行效果:弹窗直接出现在鼠标悬停位置,效果截图如下:

- 期望实现效果:鼠标悬停对应区域时,在地图右上角固定展示信息,目标效果截图如下:

上述目标效果参考自Leaflet官方choropleth示例
我尝试添加了如下自定义JS代码,但并未实现预期效果:
my_js = ''' var info = L.control({position: 'topright'}); info.onAdd = function (usa_map) { this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info" this.update(); return this._div; }; // method that we will use to update the control based on feature properties passed info.update = function (props) { this._div.innerHTML = '<h4>US Population Density</h4>' + (gdf_usa_new ? '<b>' + gdf_usa_new + '</b><br />' : 'Hover over a state'); };''' usa_map.get_root().script.add_child(Element(my_js))
解决方案
你的自定义JS未生效核心有4个问题:
- 定义
info控件后没有将控件添加到地图实例中 - 没有给行政区域面对象绑定
mouseover/mouseout事件,无法触发信息更新 - 前端JS环境无法直接读取Python端的
gdf_usa_new变量,需要从图层要素的属性中取数 - 没有给
info控件添加基础样式,会导致内容排版错乱
可直接运行的修改后完整代码
import dload from shapely.geometry import shape import geopandas as gpd import pandas as pd import folium from folium import Element json_string = 'https://raw.githubusercontent.com/datasets/geo-admin1-us/master/data/admin1-us.geojson' j = dload.json(json_string) gdf_usa = gpd.GeoDataFrame.from_features(j["features"]) gdf_usa_new = gpd.GeoDataFrame(gdf_usa, crs="EPSG:4326", geometry='geometry') # 生成底图,关闭默认跟随鼠标的悬浮提示 usa_map = gdf_usa_new.explore(tiles='CartoDB positron', tooltip=False, name='states') # 计算州中心点添加文字标注 gdf_usa_new["long"] = gdf_usa_new.to_crs(epsg='4326').centroid.map(lambda p: p.x) gdf_usa_new["lat"] = gdf_usa_new.to_crs(epsg='4326').centroid.map(lambda p: p.y) for i in range(0,len(gdf_usa_new)): folium.Marker( location=[gdf_usa_new.iloc[i]['lat'], gdf_usa_new.iloc[i]['long']], popup=gdf_usa_new.iloc[i]['name'], icon=folium.DivIcon(html=f"""<div style="font-family: courier new; color: white; font-size:10px; text-shadow:1px 1px 1px #000">{gdf_usa_new.iloc[i]['name']}</div>""") ).add_to(usa_map) # 添加右上角信息控件的自定义样式 css = ''' <style> .info { padding: 6px 8px; font: 14px/16px Arial, Helvetica, sans-serif; background: white; background: rgba(255,255,255,0.9); box-shadow: 0 0 15px rgba(0,0,0,0.2); border-radius: 5px; } .info h4 { margin: 0 0 5px; color: #777; } </style> ''' usa_map.get_root().html.add_child(Element(css)) # 添加完整交互逻辑 my_js = ''' // 初始化右上角信息控件 var info = L.control({position: 'topright'}); info.onAdd = function (map) { this._div = L.DomUtil.create('div', 'info'); this.update(); return this._div; }; info.update = function (props) { this._div.innerHTML = '<h4>美国州信息</h4>' + (props ? '<b>' + props.name + '</b>' : '鼠标悬停查看州名称'); }; info.addTo(usa_map); // 遍历地图图层,给行政区域面绑定悬停事件 usa_map.eachLayer(function(layer) { if(layer.feature && layer.feature.geometry.type.includes('Polygon')){ // 悬停时更新信息控件、高亮区域 layer.on('mouseover', function(e){ info.update(layer.feature.properties); e.target.setStyle({weight:3, color:'#666', fillOpacity:0.7}); }); // 移出时重置信息、取消高亮 layer.on('mouseout', function(e){ info.update(); e.target.setStyle({weight:2, color:'#3388ff', fillOpacity:0.2}); }) } }) ''' usa_map.get_root().script.add_child(Element(my_js)) usa_map
内容的提问来源于stack exchange,提问作者Isaac A
相关产品推荐
相关产品推荐

