Reputation: 65
This is my attempt at the animation I am trying to make:
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)
I would like to get the following figure (which is what I get when I call animate(1)
), but expanding from just a point to that size:
Click to see figure.
I know that I am not supposed to return ax
, because I get the error message TypeError: 'AxesSubplot' object is not iterable
. I don't know, however, what animate
should be returning. Any help you could give would be amazing!
Upvotes: 1
Views: 95
Reputation: 9796
You are supposed to return a sequence of Artists
, in this case
return circle1, circle2, circle3, circle4, circle5, circle6, circle7
But it seems you also want the annotations to get updated, so you'd have to return those as well.
text1 = plt.annotate('',(.5,.5-.1*t),(.5,.5),arrowprops={'width':1,'color':'k'})
# etc...
return circle1, ..., circle7, text1, text2, text3
Instead of having multiple names, such as circle1
, circle2
, etc, put all the Circle
objects in a list and then access them with circles[index]
. That way you can update the radius of the original objects instead of creating new ones in each animate
call.
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)
Upvotes: 1