想写数据动态可视化很久了,但是网上竟然没有一份能直接用的代码,昨天终于狠下心来死啃了一波开发者文档搞定了这部分,贴一篇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层会一帧一帧地刷新图像,这样只要你的数据在变,图像就会是变化的,给一张效果图: