前情提要
在matplotlib模块中我们前面学习绘制如折线、柱状、散点、直方图等静态图形。我们都知道在matplotlib模块主要有三层脚本层为用户提供快捷的绘制图形方法,美工层接收到脚本层的命令后将绘制指令发送给后端,后端提供执行绘制操作、事件响应、图形渲染工作。具体的详情可见往期文章。
在matplotlib模块中,除了以上静态图形的绘制,还提供Animation类支持绘制动态图制作。
1、基础知识
1.1、Animation 概述
Animation 是matplotlib模块制作实时动画的动画类,包含三个子类
- Animation 是动画类的基类
- TimedAnimation 是 Animation的子类,可通过绘制时间绘制每一帧动画
- FuncAnimation 是基于Timed子类,可以通过重复调用fun()方法来绘制动画
- ArtistAnimation 使用一组Artist对象来绘制动画
1.1.1、绘制动画特点
- 绘制对象引用:动画对象要在制作动画时要保持长期有效,否则会被系统资源回收,动画暂停
- 动画计时器:是对动画对象推进的唯一引用对象
- 动画保存:需要使用animation.save、animation.To_html5_video或animation.To_jshtml进行动画保存
- matpoltlib.animation 还提供关于电影格式的类
1.1.2、动画制作方法
matplotlib.animation.Animation()是动画类的基类,是不能被使用的。常用的两个类主要animation两个子类
- matplotlib.animation.FuncAnimation
matplotlib.animation.FuncAnimation(fig, func,
frames=None,
init_func=None,
fargs=None,
save_count=None,
* , cache_frame_data=True,
**kwargs)
- matplotlib.animation.ArtistAnimation
matplotlib.animation.ArtistAnimation(fig,
artists,
*args,
**kwargs)
1.2、动态图绘制的本质
动态绘图的本质就是,反复的调用一个函数或执行一串代码,每次执行就生成一幅图,覆盖掉之前的图像,呈现“动态”效果
1.3、绘制动态图步骤
matplotlib 绘制动态图最重要的是要准备好每一帧显示的数据,通常我们使用FuncAnimation可以传入产生连续数字的func方法,因此绘制动态图主要步骤为:
- 导入绘制图形的matplotlib.pyplot和制作动态图的matplotlib.animation
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
- 使用Pyplot.subplots创建一个fig画布对象和一组子图
fig,ax = plt.subplots()
- 调用numpy.random或者numpy.arange()等方法准备x,y轴数据
x = np.arange(0, 2*np.pi, 0.01)
- Axes对象调用plot()、scatter()、hist()等绘制方法,并赋值给list对象
line, = ax.plot(x, np.cos(x),color="pink")
- 需要定义一个专门update data方法生成每一帧显示的数据例如func()
def update(i):
line.set_ydata(np.cos(x + i / 50))
return line,
- 调用animation.FuncAnimation把fig和update()方法
ani = animation.FuncAnimation(
fig, update, interval=20, blit=True, save_count=50)
- 调用plt.show()显示出动态图
plt.show()
- 我们可以调用
animation.save("movie.gif",writer="pillow")
保存动画为gif格式
ps:我们需要提前pip install pillow
安装pillow库,否则会提示无法使用
ani.save("movie.gif",writer='pillow')
2、FuncAnimation参数介绍
- FuncAnimation(fig,func,frames,init_func,interval,blit)是绘制动图的主要函数,其参数如下:
- fig 绘制动图的画布名称
- func自定义动画函数,即下边程序定义的函数update
- frames动画长度,一次循环包含的帧数,在函数运行时,其值会传递给函数update(n)的形参“n”
- init_func自定义开始帧,即传入刚定义的函数init,初始化函数
- interval更新频率,以ms计
- blit选择更新所有点,还是仅更新产生变化的点。应选择True,但mac用户请选择False,否则无法显示
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots() #生成子图,相当于fig = plt.figure(),ax = fig.add_subplot(),其中ax的函数参数表示把当前画布进行分割,例:fig.add_subplot(2,2,2).表示将画布分割为两行两列 #ax在第2个子图中绘制,其中行优先,
xdata, ydata = [], [] #初始化两个数组
ln, = ax.plot([], [], 'r-', animated=False) #第三个参数表示画曲线的颜色和线型,具体参见:https://blog.csdn.net/tengqingyong/article/details/78829596
def init():
ax.set_xlim(0, 2*np.pi) #设置x轴的范围pi代表3.14...圆周率,
ax.set_ylim(-1, 1) #设置y轴的范围
return ln, #返回曲线
def update(n):
xdata.append(n) #将每次传过来的n追加到xdata中
ydata.append(np.sin(n))
ln.set_data(xdata, ydata) #重新设置曲线的值
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 10), #这里的frames在调用update函数是会将frames作为实参传递给“n”
init_func=init, blit=True)
plt.show()
PS:一般来说一个动图有两类函数,一类是初始化函数,另一类是需要更新的函数!!
动图绘制的路线
3、动态图的保存
3.1、保存为html格式
保存为HTML格式,是不需要安装额外软件的
导入模块加上这一条:
from matplotlib.animation import HTMLWriter
最后加上这一条:
mywriter = HTMLWriter(fps=60)
ani.save('myAnimation.html',writer=mywriter)
3.2、 保存为gif格式
保存为gif格式,需要下载一个imagemagick软件软件来源imagemagick
下载的是dll,下载到任何文件夹下应该都可以。
代码部分相当简单,只需要在最后加一条:
ani.save('decay.gif',writer='imagemagick',fps=30)
3.3、保存为MP4格式
3.3.1、用imagemagick保存
如果下了imagemagick,里面自带了ffmpeg的dll,那么也只需要在最后加一条:
ani.save('decay.gif',writer='ffmpeg',fps