[在下面的Python代码中,我试图制作一个围绕原点旋转2个向量的动画。我在Ubuntu 20.04上使用matplotlib 3.2.1和Python 3.8.2。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
r = 2.0
def circle(phi):
return np.array([r*np.cos(phi), r*np.sin(phi)])
fig, ax = plt.subplots(figsize=(10,6))
ax.axis([-3.5*r,3.5*r,-2.5*r,2.5*r])
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# set equal aspect
ax.set_aspect("equal")
point, = ax.plot(0, r, marker="o")
traj = plt.Circle((0,0), r, fill=False, color='black')
ax.add_artist(traj) # draw the circular trajectory
def update(phi):
x, y = circle(phi)
point.set_data([x], [y])
er_vec = np.array([0.5*x, 0.5*y])
eθ_vec = np.array([-0.5*y, 0.5*x])
er_arr = plt.arrow(x, y, dx=er_vec[0], dy=er_vec[1], head_width=0.1, head_length=0.2, color='gray')
eθ_arr = plt.arrow(x, y, dx=eθ_vec[0], dy=eθ_vec[1], head_width=0.1, head_length=0.2, color='grey')
annot_er = plt.text(1.7*x, 1.7*y, r'$\mathbf{e}_r$', fontsize=11)
annot_eθ = plt.text(1.1*(x-0.5*y), 1.1*(y+0.5*x), r'$\mathbf{e}_\theta$', fontsize=11)
ax.add_artist(er_arr)
ax.add_artist(eθ_arr)
ax.add_artist(annot_er)
ax.add_artist(annot_eθ)
return point, er_arr, eθ_arr, annot_er, annot_eθ
anim = FuncAnimation(fig, update, interval=10, blit=True, repeat=False, frames=np.linspace(0, 2.0*np.pi, 360, endpoint=False))
plt.show()
上面的代码运行流畅,没有任何问题。这是动画的屏幕截图:
但是,当我尝试将动画保存到mp4视频中时:
anim.save('anim-issue.mp4', writer='ffmpeg')
视频中的动画带有痕迹,类似于此屏幕截图:
有人可以帮我解决视频动画的问题吗?
感谢您的帮助。
编辑1:根据this answer,这归因于blit=True
。但这并不能解决问题,因为箭头没有set_position
方法。
Edit 2:我发现了另一个related question,具有与上述相同的问题,但我不知道如何修改我的代码以使其在两种情况下均能正常工作(plt.show
,anim.save
)。
更新箭头的位置非常棘手。最简单的解决方案的确是在每个帧上创建新箭头,但是必须确保先删除先前的箭头
完整代码:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
r = 2.0
def circle(phi):
return np.array([r*np.cos(phi), r*np.sin(phi)])
fig, ax = plt.subplots(figsize=(10,6))
ax.axis([-3.5*r,3.5*r,-2.5*r,2.5*r])
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# set equal aspect
ax.set_aspect("equal")
point, = ax.plot(0, r, marker="o")
traj = plt.Circle((0,0), r, fill=False, color='black')
ax.add_artist(traj) # draw the circular trajectory
er_arr = None
eθ_arr = None
annot_er = None
annot_eθ = None
def init():
global er_arr, eθ_arr, annot_er, annot_eθ
x,y = 0,0
er_vec = np.array([0.5*x, 0.5*y])
eθ_vec = np.array([-0.5*y, 0.5*x])
er_arr = plt.arrow(x, y, dx=er_vec[0], dy=er_vec[1], head_width=0.1, head_length=0.2, color='gray')
eθ_arr = plt.arrow(x, y, dx=eθ_vec[0], dy=eθ_vec[1], head_width=0.1, head_length=0.2, color='grey')
annot_er = plt.text(1.7*x, 1.7*y, r'$\mathbf{e}_r$', fontsize=11)
annot_eθ = plt.text(1.1*(x-0.5*y), 1.1*(y+0.5*x), r'$\mathbf{e}_\theta$', fontsize=11)
return er_arr, eθ_arr, annot_er, annot_eθ
def update(phi):
global er_arr, eθ_arr, annot_er, annot_eθ
x, y = circle(phi)
point.set_data([x], [y])
er_vec = np.array([0.5*x, 0.5*y])
eθ_vec = np.array([-0.5*y, 0.5*x])
#remove previous artists
er_arr.remove()
eθ_arr.remove()
er_arr = plt.arrow(x, y, dx=er_vec[0], dy=er_vec[1], head_width=0.1, head_length=0.2, color='gray')
eθ_arr = plt.arrow(x, y, dx=eθ_vec[0], dy=eθ_vec[1], head_width=0.1, head_length=0.2, color='grey')
annot_er.set_position((1.7*x, 1.7*y))
annot_eθ.set_position((1.1*(x-0.5*y), 1.1*(y+0.5*x)))
return point, er_arr, eθ_arr, annot_er, annot_eθ
anim = FuncAnimation(fig, update, init_func=init, interval=10, blit=True, repeat=False, frames=np.linspace(0, 2.0*np.pi, 360, endpoint=False))
plt.show()