如何为带GeoJSON时间轴的Python Folium地图添加动态文本框
实现Folium时间轴地图的动态永久文本展示
解决方案思路
通过自定义JavaScript监听时间轴的时间变化事件,结合页面上的固定HTML文本容器,实现随时间轴同步更新的永久可见文本。核心是利用Folium底层的Leaflet事件机制,捕获TimestampedGeoJson的时间更新动作,根据当前时间匹配预设的事件文本并实时更新显示。
具体实现步骤
1. 定义时间-事件文本映射
先整理好每个关键时间点对应的展示文本:
time_events = { "2017-06-02T00:00:00": "2017年事件:开始第一段行程", "2017-06-02T00:10:00": "2017年事件:到达汉堡点位", "2017-06-02T00:40:00": "2017年事件:完成第一段停留" # 可根据需求添加更多时间-文本对应关系 }
2. 向地图添加固定文本容器
在地图页面上添加一个悬浮的HTML文本框,用于展示动态内容:
# 添加固定文本容器到地图 folium.Html( '<div id="time-event-text" style="position: fixed; top: 10px; right: 10px; background: white; padding: 10px; border: 2px solid #333; border-radius: 5px; font-size: 14pt; z-index: 1000;"></div>', script=True ).add_to(m)
z-index:1000确保文本框始终在地图图层上方,不会被遮挡。
3. 注入JavaScript监听时间变化
编写JS代码捕获时间轴的切换事件,匹配对应文本并更新容器内容:
# 注入自定义JavaScript js_code = f""" // 获取时间文本容器 const textContainer = document.getElementById('time-event-text'); // 获取TimestampedGeoJson图层 const timestampLayer = document.querySelector('.leaflet-timestamped-geojson'); // 定义时间-事件映射 const timeEvents = {time_events}; // 监听时间变化事件 timestampLayer.addEventListener('change', function(e) {{ const currentTime = e.detail.time; let displayText = ''; // 排序时间键,找到当前时间对应的最新事件 const sortedTimes = Object.keys(timeEvents).sort((a,b) => new Date(a) - new Date(b)); for (let i = sortedTimes.length - 1; i >= 0; i--) {{ if (new Date(sortedTimes[i]) <= new Date(currentTime)) {{ displayText = timeEvents[sortedTimes[i]]; break; }} }} textContainer.innerHTML = displayText; }}); """ # 将JS代码添加到地图 m.get_root().html.add_child(folium.Element(js_code))
4. 完整修改后的代码
整合上述部分到原代码中,修正了原代码的参数错误:
import folium from folium import plugins from folium.plugins import TimestampedGeoJson # 替换为你的地图中心坐标 latitude, longitude = 53.550341, 10.000654 # 创建地图 m = folium.Map(location=[latitude, longitude], zoom_start=4) # 定义时间-事件文本映射 time_events = { "2017-06-02T00:00:00": "2017年事件:开始第一段行程", "2017-06-02T00:10:00": "2017年事件:到达汉堡点位", "2017-06-02T00:40:00": "2017年事件:完成第一段停留" } # 添加固定文本容器到地图 folium.Html( '<div id="time-event-text" style="position: fixed; top: 10px; right: 10px; background: white; padding: 10px; border: 2px solid #333; border-radius: 5px; font-size: 14pt; z-index: 1000;"></div>', script=True ).add_to(m) # 创建点位数据 points=[ { "times": ["2017-06-02T00:10:00", "2017-06-02T00:40:00"], "popup": "<h1>Some text 1</h1>", "coordinates": [10.000654, 53.550341], # 经度在前 }, # 更多点位 ] # 创建线路数据 lines = [ { "coordinates": [ [28.9662187, 41.0091982], # 经度在前 [10.000654, 53.550341], ], "times": ["2017-06-02T00:00:00", "2017-06-02T00:10:00"], }, # 更多线路 ] # 构建GeoJSON要素列表 features=[] # 添加点位要素 for point in points: features.append( { "type": "Feature", "geometry": { "type": "Point", "coordinates": point["coordinates"], }, "properties": { "times": point["times"], "popup": point["popup"], }, } ) # 添加线路要素 for line in lines: features.append( { "type": "Feature", "geometry": { "type": "LineString", "coordinates": line["coordinates"], }, "properties": { "times": line["times"], # 修正原代码中line["dates"]的错误 "popup": "Some Line Text", }, } ) # 创建时间轴GeoJSON图层并添加到地图 timestamped_geojson = plugins.TimestampedGeoJson( { "type": "FeatureCollection", "features": features, }, period="PT1M", add_last_point=True, ) timestamped_geojson.add_to(m) # 注入自定义JavaScript js_code = f""" // 获取时间文本容器 const textContainer = document.getElementById('time-event-text'); // 获取TimestampedGeoJson图层 const timestampLayer = document.querySelector('.leaflet-timestamped-geojson'); // 定义时间-事件映射 const timeEvents = {time_events}; // 监听时间变化事件 timestampLayer.addEventListener('change', function(e) {{ const currentTime = e.detail.time; let displayText = ''; // 排序时间键,找到当前时间对应的最新事件 const sortedTimes = Object.keys(timeEvents).sort((a,b) => new Date(a) - new Date(b)); for (let i = sortedTimes.length - 1; i >= 0; i--) {{ if (new Date(sortedTimes[i]) <= new Date(currentTime)) {{ displayText = timeEvents[sortedTimes[i]]; break; }} }} textContainer.innerHTML = displayText; }}); """ # 将JS代码添加到地图 m.get_root().html.add_child(folium.Element(js_code)) # 保存地图 m.save('timeline_map.html')
关键说明
- 修正了原代码中
line["dates"]的参数错误,改为line["times"],避免GeoJSON加载失败。 - JavaScript通过
leaflet-timestamped-geojson类名定位时间轴图层,确保能捕获到时间切换事件。 - 时间匹配逻辑会自动找到当前时间点之前的最新事件文本,保证文本展示与时间轴进度同步。
- 文本容器使用
position: fixed固定在地图右上角,不会随地图平移缩放移动,实现永久可见。
内容的提问来源于stack exchange,提问作者A-B
相关产品推荐
相关产品推荐

