如何在Matplotlib动画绘图中为运动点添加环绕圆形?
解决Matplotlib动画中为运动点添加环绕圆形的问题
你的代码存在两个关键问题:
- 每次执行
animate函数都新建圆形patch并添加到轴上,导致旧的圆形不会被清除,动画会越来越卡且画面混乱 plt.Circle((xdata, ydata), 2)中的xdata和ydata是数组,而Circle构造函数只接受单个坐标对,不能直接传入数组
正确的做法是提前初始化所有需要的圆形patch,在动画帧更新时只修改它们的位置,而不是每次创建新的patch。
修正后的最小可复现示例
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation, PillowWriter # 模拟变量 sim_time = 4 # 总模拟时间 dt = 0.5 # 时间步长 t = np.arange(0, sim_time, dt) T = len(t) # 帧数 fig, ax = plt.subplots() xlimit, ylimit = [-1, 26], [-1, 16] ax.set_xlim(xlimit) ax.set_ylim(ylimit) # 初始化点和圆形 num_points = 3 points, = ax.plot([], [], 'o') # 提前创建所有圆形patch,初始位置设为不可见 circles = [plt.Circle((0, 0), 2, color='r', fill=False, visible=False) for _ in range(num_points)] for circle in circles: ax.add_patch(circle) def init(): points.set_data([], []) for circle in circles: circle.set_visible(False) return points, *circles def animate(frame): xdata = np.random.rand(num_points)*10 ydata = np.random.rand(num_points)*10 # 更新点的位置 points.set_data(xdata, ydata) # 更新每个圆形的位置并设置可见 for x, y, circle in zip(xdata, ydata, circles): circle.set_center((x, y)) circle.set_visible(True) return points, *circles anim = FuncAnimation(fig, animate, init_func=init, frames=T, interval=20, blit=True) writergif = PillowWriter(fps=24) anim.save('pedestrians.gif', writer=writergif)
原代码的修正版本
针对你提供的原始代码,修改逻辑一致:提前初始化对应数量的圆形patch,在animate中更新位置即可。
import matplotlib.pyplot as plt from launcher import sol, T, dt from matplotlib.animation import FuncAnimation, PillowWriter from create import p, N, walls_x, walls_y # 转换sol.y为可绘图数组 def sol_convert(sol): x = sol.y[0::4,:] # 每个点有4个值(x,y,vx,vy) y = sol.y[1::4,:] vx = sol.y[2::4,:] vy = sol.y[3::4,:] return x, y, vx ,vy r_x, r_y, v_x, v_y = sol_convert(sol) fig, ax = plt.subplots() xlimit, ylimit = [-1,26], [-1,16] ax.set_xlim(xlimit) ax.set_ylim(ylimit) # 绘制墙壁 for i in range(len(walls_x)): plt.plot(walls_x[i], walls_y[i], 'k', linestyle="solid") # 初始化点和圆形 ped, = ax.plot([], [], 'o') # 根据点的数量N创建圆形patch circles = [plt.Circle((0, 0), 2, color='r', fill=False, visible=False) for _ in range(N)] for circle in circles: ax.add_patch(circle) def init(): ped.set_data([], []) for circle in circles: circle.set_visible(False) return ped, *circles def animate(frame): xdata = r_x[:, frame] ydata = r_y[:, frame] # 更新点的位置 ped.set_data(xdata, ydata) # 更新每个圆形的位置 for x, y, circle in zip(xdata, ydata, circles): circle.set_center((x, y)) circle.set_visible(True) return ped, *circles anim = FuncAnimation(fig, animate, init_func=init, frames=T, interval=20, blit=True) writergif = PillowWriter(fps=24) anim.save('pedestrians.gif', writer=writergif)
关键修改说明
- 提前初始化圆形patch:在动画开始前创建所有需要的圆形,避免重复创建导致的性能问题和画面混乱
- 在animate中更新位置:使用
set_center()方法修改圆形的中心坐标,而不是新建patch - blit模式支持:返回值要包含所有需要更新的元素(点+所有圆形),确保blit功能正常工作
- 初始可见性设置:在init函数中设置圆形不可见,避免初始帧出现多余图形
内容的提问来源于stack exchange,提问作者ischokking
相关产品推荐
相关产品推荐

