You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为带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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:03:14