Matplotlib动画:当使用blit时,第一帧仍然在画布中

时间:2022-12-21 23:43:23

I'm trying to plot two rotating ellipses using the Matplotlib animation library, and I managed to get it working (more or less). The problem is that the first frame that is being rendered does not update, so while I got two rotating ellipses in my canvas, I also have the ellipses in their original position/orientation. Check out my simple piece of code:

我正在尝试使用Matplotlib动画库绘制两个旋转椭圆,我设法使它工作(或多或少)。问题是渲染的第一个帧没有更新,所以当我在画布中有两个旋转的椭圆时,我也有椭圆在它们的原始位置/方向上。看看我的简单代码:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)

def init():
    ax.add_patch(e1)
    ax.add_patch(e2)
    return [e1,e2]

def animate(i):
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

Any idea how to fix this? I could of course turn off blit, but that makes it horribly slow, so that's not really an option.

你知道怎么解决这个问题吗?我当然可以关闭blit,但是这使得它非常慢,所以这不是一个选项。

Thanks!

谢谢!

EDIT: Final (working) Code

编辑:最后的(工作)代码

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)
ax.add_patch(e1)
ax.add_patch(e2)

def init():
    e1.set_visible(False)
    e2.set_visible(False)
    return [e1,e2]

def animate(i):
    if i == 1:
        e1.set_visible(True)
        e2.set_visible(True)
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

2 个解决方案

#1


3  

Try this:

试试这个:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)


def init():
    return [ax]

def animate(i):
    if i==0:
        ax.add_patch(e1)
        ax.add_patch(e2)    
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

Matplotlib动画:当使用blit时,第一帧仍然在画布中

Try this other approach (not I've used only one ellipse just for testing, it also renders fine here):

尝试另一种方法(不是我只使用了一个椭圆来测试,它在这里也显示良好):

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
ax.add_patch(e1)

def init():
    e1.set_visible(False)
    return e1,

def animate(i):
    if i==0:
        e1.set_visible(True)
    e1.angle = e1.angle + 0.5
    return e1,

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

#2


3  

The proposed answer seems like a hack. You're hiding the patch for one frame, then showing it the next, for no rhyme or reason. Also, I noticed the init function gets called whenever you resize the plot, which would then make the ellipse invisible after resizing with the proposed solution.

提议的答案似乎是一个黑客。你把补丁藏在一帧中,然后在另一帧中显示出来,没有任何韵或理由。此外,我注意到,每当您调整绘图的大小时,就会调用init函数,这将使椭圆在使用所建议的解决方案调整大小之后变得不可见。

I think the correct way to do this is to set animated=True on the Ellipse objects. See the matplotlib animation documentation. Here's some code that works for me:

我认为正确的方法是在椭圆对象上设置animation =True。参见matplotlib动画文档。下面是一些对我有用的代码:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60, animated=True)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100, animated=True)
ax.add_patch(e1)
ax.add_patch(e2)

def init():
    return [e1, e2]

def animate(i):
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1, e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

#1


3  

Try this:

试试这个:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)


def init():
    return [ax]

def animate(i):
    if i==0:
        ax.add_patch(e1)
        ax.add_patch(e2)    
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

Matplotlib动画:当使用blit时,第一帧仍然在画布中

Try this other approach (not I've used only one ellipse just for testing, it also renders fine here):

尝试另一种方法(不是我只使用了一个椭圆来测试,它在这里也显示良好):

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
ax.add_patch(e1)

def init():
    e1.set_visible(False)
    return e1,

def animate(i):
    if i==0:
        e1.set_visible(True)
    e1.angle = e1.angle + 0.5
    return e1,

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

#2


3  

The proposed answer seems like a hack. You're hiding the patch for one frame, then showing it the next, for no rhyme or reason. Also, I noticed the init function gets called whenever you resize the plot, which would then make the ellipse invisible after resizing with the proposed solution.

提议的答案似乎是一个黑客。你把补丁藏在一帧中,然后在另一帧中显示出来,没有任何韵或理由。此外,我注意到,每当您调整绘图的大小时,就会调用init函数,这将使椭圆在使用所建议的解决方案调整大小之后变得不可见。

I think the correct way to do this is to set animated=True on the Ellipse objects. See the matplotlib animation documentation. Here's some code that works for me:

我认为正确的方法是在椭圆对象上设置animation =True。参见matplotlib动画文档。下面是一些对我有用的代码:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60, animated=True)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100, animated=True)
ax.add_patch(e1)
ax.add_patch(e2)

def init():
    return [e1, e2]

def animate(i):
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1, e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()