使用python matplotlib实现动图绘制

前言

想写数据动态可视化很久了,但是网上竟然没有一份能直接用的代码,昨天终于狠下心来死啃了一波开发者文档搞定了这部分,贴一篇blog记录一下希望可以帮到你。

思路

动图的核心函数是matplotlib.animation.FuncAnimation,基本用法:

anim = animation.funcanimation(fig, animate, init_func=init, frames=100, interval=20, blit=true)
# fig: 是我们创建的画布
# animat: 是重点,是我们每个时刻要更新图形对象的函数,返回值和init_func相同
# init_func: 初始化函数,其返回值就是每次都要更新的对象,
#    告诉FuncAnimation在不同时刻要更新哪些图形对象
# frames: 相当于时刻t,要模拟多少帧图画,不同时刻的t相当于animat的参数
# interval: 刷新频率,毫秒
# blit: blit是一个非常重要的关键字,它告诉动画只重绘修改的部分,结合上面保存的时间,
#    blit=true会使动画显示得会非常非常快

动图绘制的关键是动态更新数据并刷新图像,更新数据需要写一个animat函数,看具体实现:

实现

给出代码及对应注释,你应该会秒懂:

# -*-coding:utf-8-*-
import random
from matplotlib.backends.backend_agg import FigureCanvas




from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
import seaborn as sns
from matplotlib.image import imread











gesture_i = [0] * 2200
gesture_q = [0] * 2200
acc_first = [0] * 6
acc_second = [0] * 6

acc_first_max_index = 0
acc_second_max_index = 0
acc_first_max = 0
acc_second_max = 0

cur_data_count = 0

update_first_flag = False
update_second_flag = False








name_list = ["Static", "Approach", "Apart", "Click", "Flip", "Circle"]

# 创建画布,包含4个子图
fig = plt.figure(figsize=(15, 10))

bgimg=imread("bac2.jpg")#设置背景图片
fig.figimage(bgimg,resize=True)#设置窗口自适应(背景图片)



ax1 = fig.add_subplot(2, 2, 1)
ax1.set_facecolor('none')#设置该子图背景透明,其他子图同理


ax2 = fig.add_subplot(2, 2, 3)
ax2.set_facecolor('none')



ax3 = fig.add_subplot(2, 2, 2)
ax3.set_facecolor('none')

ax4 = fig.add_subplot(2, 2, 4)
ax4.set_facecolor('none')

# 绘制初始图形
bar1 = ax3.bar(range(len(acc_first)), acc_first, color='rgb', tick_label=name_list)


bar2 = ax4.bar(range(len(acc_first)), acc_first, color='rgb', tick_label=name_list)


x = np.arange(0, 2200, 1)  # x轴

ax1.set_ylim(-1, 1)#设置y轴范围为-1到1
line1, = ax1.plot(x, gesture_i,color='coral')

ax2.set_ylim(-1, 1)
line2, = ax2.plot(x, gesture_q,color='coral')

#初始化函数
def init():
    # 构造开始帧函数init
    # 改变y轴数据,x轴不需要改
    line1.set_ydata(gesture_i)
    line2.set_ydata(gesture_q)
    bar1 = ax3.bar(range(len(acc_first)), acc_first, color='rgb', tick_label=name_list)
    bar2 = ax4.bar(range(len(acc_second)), acc_second, color='rgb', tick_label=name_list)

    ax1.set_xlabel("I")
    ax2.set_xlabel("Q")

    return line1, line2, ax1  # 注意返回值,我们要更新的就是这些数据

#更新图像的函数
def animate(i):
    #注意这里必须要用global声明,不然可能出现无法动态更新数据的情况
    global gesture_i
    global gesture_q
    global update_first_flag
    global update_second_flag

    line1.set_ydata(gesture_i)

    ax3.cla()
    bar1 = ax3.bar(range(len(acc_first)), acc_first, color='rgb', tick_label=name_list)
    ax3.legend()

    ax4.cla()
    bar2 = ax4.bar(range(len(acc_second)), acc_second, color='rgb', tick_label=name_list)
    ax4.legend



    return line1, line2, ax1





def draw_view():
# 调用FuncAnimation函数生成动画。参数说明:
# fig 进行动画绘制的figure
# func 自定义动画函数,即传入刚定义的函数animate
# frames 动画长度,一次循环包含的帧数
# init_func 自定义开始帧,即传入刚定义的函数init
# interval 更新频率,以ms计
# blit 选择更新所有点,还是仅更新产生变化的点。应选择True,但mac用户请选择False,否则无法显示动画
    ani = animation.FuncAnimation(fig=fig,
                                  func=animate,
                                  frames=100,
                                  init_func=init,
                                  interval=100,
                                  blit=False)
    plt.show()


if __name__ == '__main__':
    draw_view()

说明:实现动态数据可视化的思路是将绘制图像所用的数据写成全局变量,然后动态更新你的数据,UI层会一帧一帧地刷新图像,这样只要你的数据在变,图像就会是变化的,给一张效果图:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_36982160/article/details/80682460