如何基于Plotly图形对象列表创建按钮触发的动画?
解决方案
要实现通过按钮切换天气图层的动画效果,无需重复创建完整图形对象,只需基于同一个包含城市点的基础图,将不同日期的天气图层配置为动画帧(frames),再添加控制按钮即可。以下是修改后的完整代码:
import requests from bs4 import BeautifulSoup import pandas as pd import plotly.express as px import plotly.graph_objects as go # 加载城市地理数据 us_cities = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv") # 获取天气数据的时间范围 r = requests.get('https://geo.weather.gc.ca/geomet?service=WMS&version=1.3.0&request=GetCapabilities&layer=GDPS.DIAG_NW_PT1H') soup = BeautifulSoup(r.text, 'xml') start, end = soup.findAll('Dimension')[0].text.split('/')[:2] dates = pd.date_range(start, end, freq='1h').strftime('%Y-%m-%dT%H:%M:%SZ')[0::3] # 创建基础图形(仅包含城市点,不添加天气图层) base_fig = px.scatter_mapbox(us_cities, lat="lat", lon="lon", hover_name="City", hover_data=["State", "Population"], color_discrete_sequence=["black"], zoom=3, height=600, center={'lat': 42.18845, 'lon':-87.81544}, title=dates[0]) base_fig.update_layout( mapbox_style="open-street-map", margin={"r":0,"t":50,"l":0,"b":0} ) # 生成动画帧:每个帧对应一个日期的天气图层配置 frames = [] for date in dates: frame = go.Frame( data=[], # 城市点数据不变,无需重复定义 layout=go.Layout( mapbox_layers=[ { "below": 'traces', "sourcetype": "raster", "sourceattribution": "Government of Canada", "source": [ f"https://geo.weather.gc.ca/geomet/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX={{bbox-epsg-3857}}&CRS=EPSG:3857&WIDTH=1000&HEIGHT=1000&LAYERS=GDPS.DIAG_NW_PT1H&TILED=true&FORMAT=image/png&TIME={date}" ], } ], title=f"天气图层时间: {date}" ) ) frames.append(frame) # 添加动画控制按钮 base_fig.update( frames=frames, updatemenus=[ dict( type="buttons", buttons=[ dict(label="播放", method="animate", args=[None, {"frame": {"duration": 500, "redraw": True}, "fromcurrent": True, "transition": {"duration": 300}}]), dict(label="暂停", method="animate", args=[[None], {"frame": {"duration": 0, "redraw": False}, "mode": "immediate", "transition": {"duration": 0}}]), dict(label="上一步", method="animate", args=[[-1], {"frame": {"duration": 300, "redraw": True}, "transition": {"duration": 300}}]), dict(label="下一步", method="animate", args=[[1], {"frame": {"duration": 300, "redraw": True}, "transition": {"duration": 300}}]) ], direction="left", pad={"r": 10, "t": 87}, showactive=True, x=0.1, xanchor="right", y=0, yanchor="top" ) ] ) base_fig.show()
关键说明:
- 基础图复用:只创建一次包含城市点的基础图形,避免重复渲染静态数据,提升性能。
- 动画帧设计:每个帧仅更新
mapbox_layers配置和标题,不改动城市点数据,精准实现天气图层的切换。 - 按钮控制:通过
updatemenus添加播放、暂停、步进按钮,配置帧切换的时长和过渡效果,与官网示例的交互逻辑一致。
内容的提问来源于stack exchange,提问作者It_is_Chris
相关产品推荐
相关产品推荐

