注意
前往結尾下載完整的範例程式碼。
使用 Matplotlib 製作動畫#
基於其繪圖功能,Matplotlib 也提供了介面,可以使用 animation
模組來產生動畫。動畫是一連串的影格,其中每個影格對應到 Figure
上的圖表。本教學涵蓋了如何建立此類動畫的一般指南,以及可用的不同選項。更多資訊請參考 API 說明: animation
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
動畫類別#
Matplotlib 中的動畫過程可以透過 2 種不同的方式來思考
FuncAnimation
:產生第一影格的資料,然後修改每個影格的資料以建立動畫圖表。ArtistAnimation
:產生藝術家 (artist) 的清單(可迭代),這些藝術家將在動畫中的每個影格中繪製。
就速度和記憶體而言,FuncAnimation
效率更高,因為它會繪製藝術家一次,然後修改它。另一方面,ArtistAnimation
則很靈活,因為它允許在序列中動畫化任何可迭代的藝術家。
FuncAnimation
#
FuncAnimation
類別允許我們透過傳遞一個迭代地修改圖表資料的函式來建立動畫。這是透過在各種 Artist
上使用 setter 方法來實現的(範例: Line2D
、PathCollection
等)。通常,FuncAnimation
物件會接收一個我們想要動畫的 Figure
,以及一個修改在圖表上繪製資料的函式 func。它使用 frames 參數來判斷動畫的長度。interval 參數用於判斷繪製兩個影格之間的時間(以毫秒為單位)。使用 FuncAnimation
製作動畫通常需要這些步驟
像在靜態圖表中一樣繪製初始圖表。將所有已建立的藝術家(由繪圖函式傳回)儲存在變數中,以便您可以稍後在動畫函式中存取和修改它們。
建立一個動畫函式,該函式會更新給定影格的藝術家。通常,這會呼叫藝術家的
set_*
方法。建立一個
FuncAnimation
,傳遞Figure
和動畫函式。使用下列方法之一儲存或顯示動畫
pyplot.show
在視窗中顯示動畫Animation.to_html5_video
建立 HTML<video>
標籤Animation.to_jshtml
建立具有互動式 JavaScript 動畫控制項的 HTML 程式碼Animation.save
將動畫儲存到檔案
下表顯示了一些繪圖方法、它們傳回的藝術家,以及一些常用的 set_*
方法,這些方法會更新基礎資料。雖然更新資料是動畫中最常見的操作,但您也可以更新其他方面,例如顏色或文字位置。
繪圖方法 |
藝術家 |
資料設定方法 |
---|---|---|
|
||
|
||
涵蓋所有類型藝術家 (artist) 的設定方法已超出本教學文件的範圍,但可以在它們各自的文件中找到。以下是如何使用 Axes.scatter
和 Axes.plot
這些更新方法的範例。
fig, ax = plt.subplots()
t = np.linspace(0, 3, 40)
g = -9.81
v0 = 12
z = g * t**2 / 2 + v0 * t
v02 = 5
z2 = g * t**2 / 2 + v02 * t
scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s')
line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0]
ax.set(xlim=[0, 3], ylim=[-4, 10], xlabel='Time [s]', ylabel='Z [m]')
ax.legend()
def update(frame):
# for each frame, update the data stored on each artist.
x = t[:frame]
y = z[:frame]
# update the scatter plot:
data = np.stack([x, y]).T
scat.set_offsets(data)
# update the line plot:
line2.set_xdata(t[:frame])
line2.set_ydata(z2[:frame])
return (scat, line2)
ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=30)
plt.show()
ArtistAnimation
#
如果有多個不同藝術家 (artist) 儲存的資料,可以使用 ArtistAnimation
來產生動畫。這個藝術家 (artist) 列表會逐幀轉換成動畫。例如,當我們使用 Axes.barh
繪製長條圖時,它會為每個長條圖和誤差線建立許多藝術家 (artist)。要更新繪圖,需要個別從容器中更新每個長條圖並重新繪製。取而代之的是,可以使用 animation.ArtistAnimation
來單獨繪製每一幀,然後將它們拼接在一起形成動畫。長條圖競賽是這方面的一個簡單範例。
fig, ax = plt.subplots()
rng = np.random.default_rng(19680801)
data = np.array([20, 20, 20, 20])
x = np.array([1, 2, 3, 4])
artists = []
colors = ['tab:blue', 'tab:red', 'tab:green', 'tab:purple']
for i in range(20):
data += rng.integers(low=0, high=10, size=data.shape)
container = ax.barh(x, data, color=colors)
artists.append(container)
ani = animation.ArtistAnimation(fig=fig, artists=artists, interval=400)
plt.show()
動畫寫入器#
動畫物件可以使用各種多媒體寫入器 (例如:Pillow、ffpmeg、imagemagick) 儲存到磁碟。並非所有寫入器都支援所有影片格式。主要有 4 種類型的寫入器
PillowWriter
- 使用 Pillow 函式庫建立動畫。HTMLWriter
- 用於建立基於 JavaScript 的動畫。基於管道的寫入器 -
FFMpegWriter
和ImageMagickWriter
是基於管道的寫入器。這些寫入器將每一幀傳送到實用程式 (ffmpeg / imagemagick),然後將所有幀拼接在一起以建立動畫。基於檔案的寫入器 -
FFMpegFileWriter
和ImageMagickFileWriter
是基於檔案的寫入器範例。這些寫入器比它們的基於管道的替代方案慢,但對於偵錯更有用,因為它們會將每一幀儲存在檔案中,然後再將它們拼接成動畫。
儲存動畫#
寫入器 |
支援的格式 |
---|---|
.gif、.apng、.webp |
|
.htm、.html、.png |
|
所有 ffmpeg 支援的格式: |
|
所有 imagemagick 支援的格式: |
要使用任何寫入器儲存動畫,可以使用 animation.Animation.save
方法。它接受我們想要儲存動畫的檔案名稱和寫入器,寫入器可以是字串或寫入器物件。它還接受一個 *fps* 引數。這個引數與 FuncAnimation
或 ArtistAnimation
使用的 *interval* 引數不同。 *fps* 決定了**已儲存**動畫使用的影格率,而 *interval* 決定了**已顯示**動畫使用的影格率。
以下是一些範例,展示如何使用不同的寫入器儲存動畫。
Pillow 寫入器
HTML 寫入器
FFMpegWriter
Imagemagick 寫入器
(apng 的 extra_args
需要將檔案大小縮減約 10 倍)
請注意,需要單獨安裝 *ffmpeg* 和 *imagemagick*。獲取 *ffmpeg* 的跨平台方法是安裝 imageio_ffmpeg
PyPI 套件,然後設定 rcParams["animation.ffmpeg_path"] = imageio_ffmpeg.get_ffmpeg_exe()
。
腳本總執行時間: (0 分鐘 6.699 秒)