
Matplotlib 动画matplotlib.animation模块支持创建动态图表可保存为 GIF、MP4 等格式。FuncAnimation— 函数式动画 ⭐最常用的动画方式定义一个更新函数matplotlib 逐帧调用。importmatplotlib.pyplotaspltimportmatplotlib.animationasanimationimportnumpyasnp# 准备数据fig,axplt.subplots(figsize(8,5))xnp.linspace(0,2*np.pi,200)line,ax.plot(x,np.sin(x),b-,linewidth2)ax.set_xlim(0,2*np.pi)ax.set_ylim(-1.5,1.5)ax.set_title(Sine Wave Animation)# 初始化函数可选definit():line.set_ydata(np.sin(x))returnline,# 更新函数每一帧调用一次defupdate(frame):line.set_ydata(np.sin(xframe/10.0))ax.set_title(fSine Wave - Frame{frame})returnline,# 创建动画anianimation.FuncAnimation(fig,update,frames200,# 总帧数init_funcinit,# 初始化函数interval50,# 帧间隔毫秒blitTrue,# 仅重绘变化的部分性能优化repeatTrue,# 是否循环播放cache_frame_dataTrue# 缓存帧数据)plt.show()FuncAnimation 完整参数animation.FuncAnimation(fig,# Figure 对象func,# 更新函数 func(frame) - iterable_of_artistsframesNone,# 帧数据源: int / iterable / generatorinit_funcNone,# 初始化函数fargsNone,# 传给 func 的额外参数interval200,# 帧间隔毫秒repeatTrue,# 是否循环repeat_delay0,# 循环间延迟毫秒blitFalse,# 是否局部重绘更快cache_frame_dataTrue,# 缓存帧save_countNone# 保存时的帧数) 实用动画示例示例 1: 实时滚动数据fig,axplt.subplots(figsize(10,5))x_data,y_data[],[]line,ax.plot([],[],b-,linewidth2)ax.set_xlim(0,4*np.pi)ax.set_ylim(-1.5,1.5)definit():line.set_data([],[])returnline,# 使用 generator 作为帧源defframe_generator():t0whileTrue:yieldt t0.05defupdate(t):x_data.append(t)y_data.append(np.sin(t))# 只保留窗口内的数据window50line.set_data(x_data[-window:],y_data[-window:])ax.set_xlim(max(0,t-4*np.pi),max(4*np.pi,t))returnline,anianimation.FuncAnimation(fig,update,framesframe_generator,init_funcinit,interval30,blitTrue,save_count200)示例 2: 多子图同步动画fig,(ax1,ax2)plt.subplots(1,2,figsize(12,5))xnp.linspace(0,2*np.pi,100)line1,ax1.plot(x,np.sin(x))line2,ax2.plot(x,np.cos(x))ax1.set_title(sin(x))ax2.set_title(cos(x))foraxin[ax1,ax2]:ax.set_ylim(-1.5,1.5)defupdate(frame):line1.set_ydata(np.sin(xframe/10))line2.set_ydata(np.cos(xframe/10))returnline1,line2 anianimation.FuncAnimation(fig,update,frames100,interval50,blitTrue)示例 3: 散点图动画fig,axplt.subplots(figsize(8,8))ax.set_xlim(-3,3)ax.set_ylim(-3,3)scatax.scatter([],[],s50,c[],cmapviridis,vmin0,vmax1)definit():scat.set_offsets(np.empty((0,2)))returnscat,defupdate(frame):n100xnp.random.randn(n)*0.5np.cos(frame/20)*2ynp.random.randn(n)*0.5np.sin(frame/20)*2colorsnp.sqrt(x**2y**2)/3scat.set_offsets(np.c_[x,y])scat.set_array(colors)returnscat,anianimation.FuncAnimation(fig,update,frames200,init_funcinit,interval50,blitTrue)ArtistAnimation— 艺术家动画预先创建每帧的 Artist 列表然后按顺序播放。fig,axplt.subplots(figsize(8,5))artists[]foriinrange(100):# 每帧创建新的 Artist 列表ynp.sin(xi/10.0)line,ax.plot(x,y,b-)titleax.text(0.5,1.02,fFrame{i},transformax.transAxes,hacenter)artists.append([line,title])ax.set_ylim(-1.5,1.5)anianimation.ArtistAnimation(fig,artists,interval50,blitTrue,repeatTrue)FuncAnimation vs ArtistAnimationFuncAnimationArtistAnimation方式更新 Artist 数据替换整个 Artist 列表性能好推荐一般适用数据更新绘图元素变化内存低就地更新高存储所有帧 保存动画保存为 GIF# 需要 Pillowani.save(animation.gif,writerpillow,fps20,dpi100)# 控制 GIF 大小ani.save(animation.gif,writerpillow,fps15,dpi80,savefig_kwargs{bbox_inches:tight,pad_inches:0.1})保存为 MP4 视频# 需要 ffmpegani.save(animation.mp4,writerffmpeg,fps30,dpi150,bitrate1800)# HTML5 视频Jupyter NotebookfromIPython.displayimportHTML HTML(ani.to_html5_video())保存为 HTML (带控件)# 需要 ffmpeg 或 imagemagickani.save(animation.html,writerhtml,fps20)Writer 配置# 查看可用 Writerprint(animation.writers.list())# 自定义 Writerwriteranimation.FFMpegWriter(fps30,bitrate3600,codech264,extra_args[-pix_fmt,yuv420p,-preset,slow])ani.save(output.mp4,writerwriter)# PillowWriter (GIF)writeranimation.PillowWriter(fps15,bitrate1800)ani.save(output.gif,writerwriter)# 使用 imagemagickani.save(output.gif,writerimagemagick,fps20)⏯️ 交互控制# 在 Jupyter Notebook 中显示带控件的动画frommatplotlib.animationimportFuncAnimationfromIPython.displayimportHTML aniFuncAnimation(fig,update,frames100,interval50)HTML(ani.to_jshtml())# 带播放/暂停/进度条的 HTML在 Tkinter / Qt 中嵌入动画# 基本思路# 1. 创建 GUI 窗口# 2. 将 FigureCanvas 嵌入窗口# 3. 用 timer 驱动 FuncAnimation 或手动更新 高级动画技巧暂停与恢复pausedFalsedefon_click(event):globalpausedifpaused:ani.event_source.start()pausedFalseelse:ani.event_source.stop()pausedTruefig.canvas.mpl_connect(button_press_event,on_click)动态改变参数# 使用闭包或全局变量传递可变参数params{amplitude:1.0,frequency:1.0}defupdate(frame):yparams[amplitude]*np.sin(params[frequency]*xframe/10)line.set_ydata(y)returnline,# 在外部分修改 params 即可改变动画行为params[amplitude]2.0多线动画fig,axplt.subplots(figsize(10,6))xnp.linspace(0,2*np.pi,200)lines[]fori,freqinenumerate([1,2,3]):line,ax.plot(x,np.sin(freq*x),labelffreq{freq})lines.append(line)ax.legend()ax.set_ylim(-1.5,1.5)defupdate(frame):fori,lineinenumerate(lines):freqi1line.set_ydata(np.sin(freq*(xframe/30)))returnlines anianimation.FuncAnimation(fig,update,frames200,interval40,blitTrue) 动画性能优化技巧说明blitTrue仅重绘变化的元素显著提速减少帧数frames设为合理值降低分辨率保存时用较低dpi使用更少的数据点降采样避免在update中创建 Artist预先创建好设置合理的interval毫秒/帧20fps 50ms[[matplotlib3-总览|← 返回总览]]