基于Folium实现荷兰运输路线Time Lapse交互展示的技术问询
解决方案:Folium实现日期滑块路线展示
步骤1:按日期分组数据
确保你的GeoDataFrame(slibdata)包含日期列(比如命名为date),先统一日期格式并分组:
import folium from folium.plugins import FeatureGroupSubGroup import pandas as pd # 格式化日期为统一格式(如'YYYY-MM-DD') slibdata['date'] = pd.to_datetime(slibdata['date']).dt.strftime('%Y-%m-%d') # 按日期分组数据 date_groups = slibdata.groupby('date')
步骤2:创建地图与分组图层
以荷兰中心坐标为基础创建地图,为每个日期的路线单独创建FeatureGroup子图层:
# 初始化地图 m = folium.Map(location=[52.1326, 5.2913], zoom_start=7) # 创建主分组容器 main_group = folium.FeatureGroup(name='Routes by Date').add_to(m) # 按日期遍历,生成对应子图层 date_list = sorted(date_groups.groups.keys()) for date in date_list: subgroup = FeatureGroupSubGroup(main_group, name=date).add_to(m) group_data = date_groups.get_group(date) # 添加该日期的所有路线 for idx, row in group_data.iterrows(): folium.PolyLine( locations=[row['routes'][0], row['routes'][1]], weight=row['weight']/3, color='blue', tooltip=f"{row['istOmschr']} >>> {row['ist2Omschr']}" ).add_to(subgroup) # 添加该日期对应的标记(若verwerkers_info与日期关联,需先过滤再添加) for coord in verwerkers_info: folium.CircleMarker( location=[coord[1], coord[2]], tooltip=str(coord), radius=5 ).add_to(subgroup)
步骤3:添加自定义日期滑块控件
Folium无原生滑块,需手动嵌入HTML+JS实现图层切换逻辑:
# 滑块控件的HTML与JS代码 slider_html = f""" <div style="position: fixed; bottom: 50px; left: 50px; z-index: 9999; background: white; padding: 10px; border-radius: 5px;"> <label for="date-slider">选择日期:</label> <input type="range" id="date-slider" min="0" max="{len(date_list)-1}" value="0" step="1"> <span id="current-date" style="margin-left: 10px;">{date_list[0]}</span> </div> <script> var dateList = {date_list}; var slider = document.getElementById('date-slider'); var currentDateSpan = document.getElementById('current-date'); var map = window.map; // 初始仅显示第一个日期的图层 map.eachLayer(function(layer) {{ if (layer instanceof L.FeatureGroup && layer.options.name !== '{date_list[0]}') {{ layer.hide(); }} }}); // 滑块拖动事件监听 slider.addEventListener('input', function() {{ var selectedDate = dateList[this.value]; currentDateSpan.textContent = selectedDate; // 切换图层显示状态 map.eachLayer(function(layer) {{ if (layer instanceof L.FeatureGroup) {{ layer.options.name === selectedDate ? layer.show() : layer.hide(); }} }}); }}); </script> """ # 将滑块控件添加到地图 m.get_root().html.add_child(folium.Element(slider_html)) # 保存地图文件 m.save('routes_time_lapse.html')
备选方案:使用Plotly Express快速实现
如果自定义Folium控件太繁琐,Plotly Express可一键生成带时间滑块的交互地图:
import plotly.express as px # 转换路线数据格式(将每条路线拆分为起点、终点两行) plot_data = [] for idx, row in slibdata.iterrows(): start_lat, start_lon = row['routes'][0] end_lat, end_lon = row['routes'][1] plot_data.extend([ {'date': row['date'], 'lat': start_lat, 'lon': start_lon, 'route_id': idx, 'istOmschr': row['istOmschr'], 'ist2Omschr': row['ist2Omschr']}, {'date': row['date'], 'lat': end_lat, 'lon': end_lon, 'route_id': idx, 'istOmschr': row['istOmschr'], 'ist2Omschr': row['ist2Omschr']} ]) plot_df = pd.DataFrame(plot_data) # 生成带时间滑块的地图 fig = px.line_mapbox( plot_df, lat='lat', lon='lon', color='route_id', animation_frame='date', mapbox_style='carto-positron', center={'lat': 52.1326, 'lon': 5.2913}, zoom=7, hover_data=['istOmschr', 'ist2Omschr'] ) # 添加固定标记(无需随时间切换) for coord in verwerkers_info: fig.add_scattermapbox( lat=[coord[1]], lon=[coord[2]], mode='markers', marker=dict(size=10, color='red'), hovertext=str(coord), showlegend=False ) # 保存HTML文件 fig.write_html('routes_plotly_time_lapse.html')
其他工具选项
- Kepler.gl: 专注时空数据可视化的开源工具,支持拖拽上传数据,自动生成时间轴滑块,无需编写大量代码,适合快速探索数据。
- Leaflet.js: 若需要完全自定义交互逻辑,可直接使用原生Leaflet配合
Leaflet.TimeDimension插件,灵活性更高,但需要编写前端代码。
内容的提问来源于stack exchange,提问作者Herwini
相关产品推荐
相关产品推荐

