首页 > 解决方案 > 尝试用 matplotlib 制作动画

问题描述

这是我尝试制作的动画:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots(figsize=(10,10))
ax.set_xlim([0,1])
ax.set_ylim([0,1])

def animate(t):
    circle1 = plt.Circle((0.5, 0.5), 0.1*t, color='k',fill=False)
    circle2 = plt.Circle((0.5, 0.5), 0.16*t, color='deepskyblue',fill=False)
    circle3 = plt.Circle((0.5, 0.5), 0.22*t, color='deepskyblue',fill=False)
    circle4 = plt.Circle((0.5, 0.5), 0.28*t, color='deepskyblue',fill=False)
    circle5 = plt.Circle((0.5, 0.5), 0.34*t, color='deepskyblue',fill=False)
    circle6 = plt.Circle((0.5, 0.5), 0.40*t, color='deepskyblue',fill=False)
    circle7 = plt.Circle((0.5, 0.5), 0.46*t, color='k',fill=False)
    ax.add_patch(circle1)
    ax.add_patch(circle2)
    ax.add_patch(circle3)
    ax.add_patch(circle4)
    ax.add_patch(circle5)
    ax.add_patch(circle6)
    ax.add_patch(circle7)
    plt.scatter(.5,.5,color='k')
    plt.annotate('',(.5,.5-.1*t),(.5,.5),arrowprops={'width':1,'color':'k'})
    plt.annotate('',(.5+.46*t,.5),(.5,.5),arrowprops={'width':1,'color':'k'})
    plt.annotate('',(.5-.2*t,.5+.15*t),(.5,.5),arrowprops={'width':.5,'color':'red'})
    return ax

FuncAnimation(fig, animate, frames=np.arange(0.0, 1, .01), interval=10, blit=True, repeat=True)

我想得到下图(这是我打电话时得到的animate(1)),但从一个点扩展到那个大小: 点击查看图。

我知道我不应该返回ax,因为我收到了错误消息TypeError: 'AxesSubplot' object is not iterable。但是,我不知道animate应该返回什么。您能提供的任何帮助都将是惊人的!

标签: pythonmatplotlibanimation

解决方案


Artists在这种情况下,您应该返回一个序列

return circle1, circle2, circle3, circle4, circle5, circle6, circle7

但似乎您还希望注释得到更新,因此您也必须返回这些注释。

text1 = plt.annotate('',(.5,.5-.1*t),(.5,.5),arrowprops={'width':1,'color':'k'})
# etc...
return circle1, ..., circle7, text1, text2, text3

更好的方法

不要使用多个名称,例如circle1,circle2等,而是将所有Circle对象放在一个列表中,然后使用circles[index]. 这样,您可以更新原始对象的半径,而不是在每次animate调用中创建新对象。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation


def create_circles():
    radii = np.arange(0.1, .47, 0.06)
    colors = ['k'] + ['deepskyblue'] * 5 + ['k']
    circles = [plt.Circle((0.5, 0.5), color=c, fill=False) for c in colors]
    for circle in circles:
        ax.add_patch(circle)
    return circles, radii

def create_annotations():
    widths = [1, 1, .5]
    colors = ['k', 'k', 'red']
    annotations = [plt.annotate('', (.5, .5), (.5, .5), arrowprops={'width': w, 'color': c})
                   for w, c in zip(widths, colors)]
    lengths = [(0, -.1), (+.46, 0), (-.2, .15)]
    return annotations, lengths


fig, ax = plt.subplots(figsize=(10,10))
ax.set_xlim([0,1])
ax.set_ylim([0,1])

center = [plt.scatter(.5, .5, color='k')]
circles, radii = create_circles()
annotations, lengths = create_annotations()

def animate(t):
    for circle, radius in zip(circles, radii):
        circle.set_radius(radius * t)
    for ann, (x, y) in zip(annotations, lengths):
        ann.xy = (.5+x*t, .5+y*t)
    return center + circles + annotations

FuncAnimation(fig, animate, frames=np.arange(0.0, 1, .01), interval=10, blit=True, repeat=True)

推荐阅读