FuncAnimation
是matplotlib
生成动画的常用类,它的工作原理就是不断调用参数func
对应的函数生成动画。
FuncAnimation
构造方法中关键的三个参数为func
,frames
,fargs
。
func
:对于逐帧动画来说就是每一帧的生成方法。frames
:暂且不管它在底层如何实现,最终将生成一个可迭代对象,用于每次向func
生成的每一帧传递一个值。fargs
:除frames
之外需要向func
传递的参数。
在查找使用FuncAnimation
生成动画的资料过程中,发现大多数案例在编写回调函数func
时,一般都只构造1个参数,这样fargs
参数就用不到了,如果回调函数有多个参数怎么实现呢。
只使用frames
参数不使用fargs
参数的实现方法(回调函数只有一个参数)
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import numpy as np
t = np.linspace(0, 6, 100)
x = 16 * np.sin(t) ** 3
y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)
data=[i for i in zip(x,y)]
def plot_love(data):
x, y = data
plt.scatter(x, y, 60, c="r", alpha=0.7, marker=r"$\heartsuit$")
fig=plt.figure(figsize=(5, 3), dpi=100)
plt.axis("off")
animator = animation.FuncAnimation(fig, plot_love, frames=data, interval=80)
animator.save("love.gif", writer='pillow')
在这个案例中:
plot_love
就是FuncAnimation
构造方法中的func
参数,也即回调函数。
frames
参数的取值是data
,data
是一个构造好的二元组-列表,plot_love
每次调用从中取一个值。
使用fargs
参数的实现方法(回调函数多个参数)
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import numpy as np
t = np.linspace(0, 6, 100)
x = 16 * np.sin(t) ** 3
y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)
def plot_love(num,x,y):
plt.scatter(x[:num],y[:num],60, c="r", alpha=0.7, marker=r"$\heartsuit$")
fig=plt.figure(figsize=(5, 3), dpi=100)
plt.axis("off")
animator = animation.FuncAnimation(fig, plot_love, frames=len(t), fargs=(x,y), interval=80)
animator.save("love0.gif", writer='pillow')
在这个案例中:
plot_love
就是FuncAnimation
构造方法中的func
参数,也即回调函数,这里有3个参数。
frames
参数的取值是len(t)
,len(t)
会用于构造成一个长度为len(t)
序列,依次将元素传递给回调函数plot_love
中的参数num
。
fargs
参数取值为(x,y)
,在传递给回调函数plot_love
时解包为x
,y
。
原理分析
从FuncAnimation
类的文档中可知,func
参数每帧调用一次,第一个参数frame
是frames
参数中的下一个元素,也可以说frames
是一个可迭代对象。
因此,在第一个案例中,frames
的参数值是一个值序列,每调用一次回调函数就从中取一个值,取值过程不用我们干预。
在第二个案例中,frames
的值是一个整数,但是在底层上,会利用range()
函数生成一个可迭代对象,作为第一个参数传递给回调函数,机制同第一个案例。fargs
作为可变参数传递给回调函数,该参数没有类似frames
参数的取值机制,因此,传递过去的值就是对象本身。
func : callable
The function to call at each frame. The first argument will
be the next value in *frames*. Any additional positional
arguments can be supplied via the *fargs* parameter.
The required signature is::
def func(frame, *fargs) -> iterable_of_artists
以下是FuncAnimation
类的文档字符串。
def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
save_count=None, *, cache_frame_data=True, **kwargs):
"""
Makes an animation by repeatedly calling a function *func*.
Parameters
----------
fig : `~matplotlib.figure.Figure`
The figure object used to get needed events, such as draw or resize.
func : callable
The function to call at each frame. The first argument will
be the next value in *frames*. Any additional positional
arguments can be supplied via the *fargs* parameter.
The required signature is::
def func(frame, *fargs) -> iterable_of_artists
If ``blit == True``, *func* must return an iterable of all artists
that were modified or created. This information is used by the blitting
algorithm to determine which parts of the figure have to be updated.
The return value is unused if ``blit == False`` and may be omitted in
that case.
frames : iterable, int, generator function, or None, optional
Source of data to pass *func* and each frame of the animation
- If an iterable, then simply use the values provided. If the
iterable has a length, it will override the *save_count* kwarg.
- If an integer, then equivalent to passing ``range(frames)``
- If a generator function, then must have the signature::
def gen_function() -> obj
- If *None*, then equivalent to passing ``itertools.count``.
In all of these cases, the values in *frames* is simply passed through
to the user-supplied *func* and thus can be of any type.
init_func : callable, optional
A function used to draw a clear frame. If not given, the results of
drawing from the first item in the frames sequence will be used. This
function will be called once before the first frame.
The required signature is::
def init_func() -> iterable_of_artists
If ``blit == True``, *init_func* must return an iterable of artists
to be re-drawn. This information is used by the blitting algorithm to
determine which parts of the figure have to be updated. The return
value is unused if ``blit == False`` and may be omitted in that case.
fargs : tuple or None, optional
Additional arguments to pass to each call to *func*.
save_count : int, default: 100
Fallback for the number of values from *frames* to cache. This is
only used if the number of frames cannot be inferred from *frames*,
i.e. when it's an iterator without length or a generator.
interval : int, default: 200
Delay between frames in milliseconds.
repeat_delay : int, default: 0
The delay in milliseconds between consecutive animation runs, if
*repeat* is True.
repeat : bool, default: True
Whether the animation repeats when the sequence of frames is completed.
blit : bool, default: False
Whether blitting is used to optimize drawing. Note: when using
blitting, any animated artists will be drawn according to their zorder;
however, they will be drawn on top of any previous artists, regardless
of their zorder.
cache_frame_data : bool, default: True
Whether frame data is cached. Disabling cache might be helpful when
frames contain large objects.
"""