閱讀目錄
1、引言
2、動畫實現(xiàn)
總結(jié)
注: 在“實驗設(shè)計與數(shù)據(jù)處理”的課后作業(yè)中,有一個數(shù)據(jù)可視化的作業(yè),利用課程上學(xué)習(xí)的某種方法找一個二維函數(shù)的最大值,并將這個尋找的過程可視化。在作業(yè)里面利用了Matplotlib的Animation類實現(xiàn)可視化的動態(tài)展示。
利用Animation類制動畫主要是參考了官方的教程:Matplotlib-Animation。為了更加清析說明Animation類是如何實現(xiàn)動畫的,本文只簡單地介紹一個點沿著sin函數(shù)運(yùn)動的例子,分析一下Animation實現(xiàn)動畫的原理。其它復(fù)雜的動畫同樣也是據(jù)此原理,可以實現(xiàn)下面的動畫效果。第3幅圖是作業(yè)的一個效果圖。
sin函數(shù)點運(yùn)動 二階擺鐘(官方例子)
image.png
| [
image.png
|
|
image.png
|
這里主講述上面的sin函數(shù)點運(yùn)動的動畫的實現(xiàn)。代碼的運(yùn)行環(huán)境為Python3.6 + Jupyter5.4。
2.1 準(zhǔn)備背景
在繪制動畫前,我們需將其sin函數(shù)的背景繪制出來。這一步很簡單,與我們平時的繪圖一樣。
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# 指定渲染環(huán)境
%matplotlib notebook
# %matplotlib inline
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
fig = plt.figure(tight_layout=True)
plt.plot(x,y)
plt.grid(ls='--')
plt.show
image.png
image.png
|
| 圖2-1 sin背景圖 | 圖2-2 sin函數(shù)點運(yùn)動效果1 |
2.2 往背景中添加動畫點
這一步代碼稍微多了一點點,且先看代碼,再來解釋。
def update_points(num):
'''
更新數(shù)據(jù)點
'''
point_ani.set_data(x[num], y[num])
return point_ani,
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
fig = plt.figure(tight_layout=True)
plt.plot(x,y)
point_ani, = plt.plot(x[0], y[0], 'ro')
plt.grid(ls='--')
# 開始制作動畫
ani = animation.FuncAnimation(fig, update_points, np.arange(0, 100), interval=100, blit=True)
# ani.save('sin_test2.gif', writer='imagemagick', fps=10)
plt.show
上面的代碼中,首先定義了一個update_points函數(shù),用于更新繪制的圖中的數(shù)據(jù)點。此函數(shù)的輸入?yún)?shù)num代表當(dāng)前動畫的第幾幀,函數(shù)的返回,即為我們需要更新的對象,需要特別注意的是:reuturn point_ani,這個逗號一定加上,否則動畫不能正常顯示。當(dāng)然這里面操作的點對象point_ani我們一般會提前聲明得到:point_ani, = plt.plot(x[0], y[0], 'ro')。接下來就是將此函數(shù)傳入我們的FuncAnimation函數(shù)中,函數(shù)的參數(shù)說明可以參見官網(wǎng),這里簡要說明用到的幾個參數(shù)。
第1個參數(shù)fig:即為我們的繪圖對象.
第2個參數(shù)update_points:更新動畫的函數(shù).
第3個參數(shù)np.arrange(0, 100):動畫幀數(shù),這需要是一個可迭代的對象。
interval參數(shù):動畫的時間間隔。
blit參數(shù):是否開啟某種動畫的渲染。
運(yùn)行上面代碼可以得到如圖2-2所示的動畫效果。
2.3 往動畫中添加其它效果
上面實現(xiàn)的動畫效果還比較單一,我們可以往其中添加一些文本顯示,或者在不同的條件下改變點樣式。這其實也非常簡單,只需在update_points函數(shù)中添加一些額外的,你想要的效果代碼即可。
def update_points(num):
if num%5==0:
point_ani.set_marker('*')
point_ani.set_markersize(12)
else:
point_ani.set_marker('o')
point_ani.set_markersize(8)
point_ani.set_data(x[num], y[num])
text_pt.set_text('x=%.3f, y=%.3f'%(x[num], y[num]))
return point_ani,text_pt,
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
fig = plt.figure(tight_layout=True)
plt.plot(x,y)
point_ani, = plt.plot(x[0], y[0], 'ro')
plt.grid(ls='--')
text_pt = plt.text(4, 0.8, '', fontsize=16)
ani = animation.FuncAnimation(fig, update_points, np.arange(0, 100), interval=100, blit=True)
# ani.save('sin_test3.gif', writer='imagemagick', fps=10)
plt.show
我在上面update_points函數(shù)中添加了一個文本,讓它顯示點的坐標(biāo)值,同時在不同的幀,改變了點的形狀,讓它在5的倍數(shù)幀顯示為五角星形狀。
|
image.png
|
image.png
|
| 圖2-3 sin函數(shù)點運(yùn)動效果2 | 圖2-4 sin函數(shù)點運(yùn)動效果3 |
再稍微改變一下,可以讓文本跟著點動。只需將上面的代碼update_points函數(shù)改為如下代碼,其效果如圖2-4所示。
def update_points(num):
point_ani.set_data(x[num], y[num])
if num%5==0:
point_ani.set_marker('*')
point_ani.set_markersize(12)
else:
point_ani.set_marker('o')
point_ani.set_markersize(8)
text_pt.set_position((x[num], y[num]))
text_pt.set_text('x=%.3f, y=%.3f'%(x[num], y[num]))
return point_ani,text_pt,