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

如何基于范围更新Cartopy+FuncAnimation中的瓦片地图?

解决Cartopy+FuncAnimation底图随轨迹范围更新的问题

核心问题是Cartopy的瓦片图层(如GoogleTiles)只会在首次添加时基于当前轴范围加载瓦片,轴范围变更后不会自动刷新。重复调用add_image只会叠加新瓦片,不会替换旧的,所以需要手动清理并重新加载。

具体实现步骤

  • 在动画的update函数中,先清除已加载的瓦片图层:Cartopy的Axes对象会将瓦片图层存在ax.images列表里,直接清空该列表即可(如果你的轴上只有瓦片底图的话)。
  • 根据当前帧的轨迹数据计算新的显示范围,设置轴的xlim和ylim,建议给范围加一点缓冲值(比如±0.5度),避免轨迹贴边。
  • 重新调用ax.add_image(tiler, zoom_level),此时会基于新的轴范围加载对应区域的瓦片。
  • 更新轨迹的显示(比如更新线的坐标或标记的位置)。

完整代码示例

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import cartopy.crs as ccrs
from cartopy.io.img_tiles import GoogleTiles
import geopandas as gpd
import pandas as pd

# 模拟轨迹数据:全球移动的点
dates = pd.date_range(start='2023-01-01', periods=50, freq='H')
lons = pd.Series([-180 + 7.2*i for i in range(50)])  # 从西向东绕全球
lats = pd.Series([0]*25 + [10]*25)  # 前半段赤道,后半段北纬10度
gdf = gpd.GeoDataFrame(
    {'datetime': dates},
    geometry=gpd.points_from_xy(lons, lats),
    crs='EPSG:4326'
)

# 初始化绘图
tiler = GoogleTiles(style='satellite')
proj = tiler.crs  # 瓦片使用墨卡托投影,轴要对应这个投影

fig, ax = plt.subplots(figsize=(8, 6), subplot_kw={'projection': proj})

# 初始化轨迹线和标记
trail_line, = ax.plot([], [], 'r-', transform=ccrs.Geodetic())
current_marker, = ax.plot([], [], 'ro', markersize=8, transform=ccrs.Geodetic())

# 动画初始化函数
def init():
    trail_line.set_data([], [])
    current_marker.set_data([], [])
    return trail_line, current_marker

# 动画更新函数
def update(frame):
    # 获取当前及之前的轨迹数据
    current_data = gdf.iloc[:frame+1]
    lons = current_data.geometry.x
    lats = current_data.geometry.y

    # 1. 清除旧的瓦片图层
    ax.images.clear()

    # 2. 计算并设置新的显示范围(加缓冲)
    lon_min, lon_max = lons.min() - 0.5, lons.max() + 0.5
    lat_min, lat_max = lats.min() - 0.5, lats.max() + 0.5
    # 将经纬度范围转换为墨卡托投影的坐标
    x_min, y_min = proj.transform_point(lon_min, lat_min, ccrs.Geodetic())
    x_max, y_max = proj.transform_point(lon_max, lat_max, ccrs.Geodetic())
    ax.set_xlim(x_min, x_max)
    ax.set_ylim(y_min, y_max)

    # 3. 重新添加瓦片底图
    ax.add_image(tiler, 5)  # zoom_level根据需要调整

    # 4. 更新轨迹和标记
    trail_line.set_data(lons, lats)
    current_marker.set_data(lons.iloc[-1], lats.iloc[-1])

    return trail_line, current_marker

# 创建并运行动画
ani = FuncAnimation(fig, update, frames=len(gdf), init_func=init, interval=200, blit=True)
plt.show()

注意事项

  • 确保轴的投影和瓦片的投影一致(比如GoogleTiles用的是墨卡托投影ccrs.Mercator(),所以轴的projection要设为tiler.crs)。
  • 缩放级别zoom_level可以根据轨迹的范围调整,范围越小(比如局部区域)可以设更高的级别,范围越大(比如全球)设较低级别。
  • 如果你的轴上还有其他图像元素,不要直接ax.images.clear(),可以通过判断元素的类型来筛选清除瓦片:比如遍历ax.images,移除那些是cartopy.mpl.singleton_artist.SingletonArtist类型的(瓦片图层的类型)。

内容的提问来源于stack exchange,提问作者August

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:13:12