首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Matplotlib 動畫完整指南:FuncAnimation 核心機制、四種更新模式、效能優化與實戰範例

     編輯:更多程式設計知識

Matplotlib 1.1+ 內建 animation 模組,透過 FuncAnimation 實現幀級動畫渲染。核心機制:周期性呼叫更新函式、修改繪圖物件資料、重繪畫布。本文系統解析四種資料來源模式、blit 技術、儲存輸出、效能調優與五個完整實戰範例。

核心架構


ani = animation.FuncAnimation(
    fig,              # Figure 物件
    func,             # 更新函式 (每幀呼叫)
    frames,           # 幀資料來源 (int/iterable/generator)
    init_func,        # 初始化函式 (可選,blit 需要)
    interval,         # 幀間隔 (毫秒)
    blit,             # 是否只重繪變化部分 (關鍵優化)
    repeat,           # 是否循環
    save_count        # 儲存時幀數
)

四種 frames 來源模式詳解

模式一:生成器函式 — 無限串流、動態資料


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)

def data_gen():
    """無限生成器:每次 yield 新資料"""
    while True:
        yield np.random.rand(10)

def update(data):
    line.set_ydata(data)
    return line,

ani = animation.FuncAnimation(fig, update, data_gen, interval=2000, blit=True)
plt.show()

特點:update 參數直接接收 yield 的值,非幀號。適用即時串流、感測器資料、模擬系統。

模式二:列表/陣列 — 預載資料、有限幀數


fig, ax = plt.subplots()
line, = ax.plot([1, 0.18, 0.63, 0.29, 0.03, 0.24, 0.86, 0.07, 0.58, 0])

metric = [
    [0.03, 0.86, 0.65, 0.34, 0.34, 0.02, 0.22, 0.74, 0.66, 0.65],
    [0.43, 0.18, 0.63, 0.29, 0.03, 0.24, 0.86, 0.07, 0.58, 0.55],
    [0.66, 0.75, 0.01, 0.94, 0.72, 0.77, 0.20, 0.66, 0.81, 0.52]
]

def update(data):
    line.set_ydata(data)
    return line,

# frames 直接傳列表,每幀取一個元素
ani = animation.FuncAnimation(fig, update, metric, interval=2000, blit=True)
plt.show()

特點:frames 為列表時,每幀自動取一個元素傳給 update。適用預計算軌跡、關鍵幀動畫。

模式三:幀號整數 — 程式化生成、數學函數動畫


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()
ax.set_xlim(0, 2)
ax.set_ylim(-2, 2)
line, = ax.plot([], [], lw=2)

def init():
    line.set_data([], [])
    return line,

def animate(frame_num):
    """frame_num 從 0 遞增"""
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * frame_num))
    line.set_data(x, y)
    return line,

# frames=200 表示 0..199
ani = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=True)
plt.show()

特點:frames 為整數時,update 參數為幀號 (0,1,2...)。適用數學函數、物理模擬、參數化動畫。

模式四:生成器 + 狀態保持 — 長序列、動態範圍調整


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def data_gen():
    t = 0
    cnt = 0
    while cnt < 1000:
        cnt += 1
        t += 0.05
        yield t, np.sin(2*np.pi*t) * np.exp(-t/10.)

fig, ax = plt.subplots()
line, = ax.plot([], [], lw=2)
ax.set_ylim(-1.1, 1.1)
ax.set_xlim(0, 5)
ax.grid()
xdata, ydata = [], []

def run(data):
    t, y = data
    xdata.append(t)
    ydata.append(y)
    
    # 動態擴展 X 軸
    xmin, xmax = ax.get_xlim()
    if t >= xmax:
        ax.set_xlim(xmin, 2*xmax)
        ax.figure.canvas.draw()
    
    line.set_data(xdata, ydata)
    return line,

ani = animation.FuncAnimation(fig, run, data_gen, blit=True, interval=10, repeat=False)
plt.show()

特點:生成器維持狀態 (t, cnt),run 累積資料並動態調整座標軸。適用長時間監控、示波器、軌跡繪製。

模式五:fargs 傳遞額外參數 — 固定資料集、索引存取


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()
data = np.random.rand(2, 15)  # 2 行 15 列
line, = ax.plot([], [], 'r-')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)

def update_line(frame_num, data, line):
    """frame_num 從 0 遞增,data 為 fargs 傳入"""
    line.set_data(data[0, :frame_num], data[1, :frame_num])
    return line,

# frames=25:幀號 0..24 (資料有 15 點,超過後重複)
ani = animation.FuncAnimation(fig, update_line, 25, fargs=(data, line), interval=50, blit=True)
plt.show()

特點:fargs 傳遞固定資料,update 簽名為 (frame_num, *fargs)。適用固定資料集的逐步顯示。

關鍵優化:blit 技術 (Blitting)

模式blit=Falseblit=True
重繪範圍整個 Figure僅回傳藝術家列表的變化區域
效能慢 (全畫布重繪)快 (部分更新)
init_func可選必要 (建立背景快取)
update 回傳任意必須回傳藝術家序列 (line,)

# blit=True 必要條件
def init():
    line.set_data([], [])
    return line,  # 必須回傳序列

def animate(i):
    line.set_data(x, y)
    return line,  # 必須回傳序列

ani = FuncAnimation(fig, animate, init_func=init, blit=True, ...)

儲存動畫輸出


# 儲存為 MP4 (需 ffmpeg)
ani.save('animation.mp4', writer='ffmpeg', fps=30, 
         extra_args=['-vcodec', 'libx264', '-pix_fmt', 'yuv420p'])

# 儲存為 GIF (需 imagemagick 或 pillow)
ani.save('animation.gif', writer='pillow', fps=10)

# 儲存為 HTML5 (內嵌 JS 播放器)
html = ani.to_jshtml()
with open('animation.html', 'w') as f:
    f.write(html)

效能調優清單

  1. 啟用 blit=True:最關鍵優化,配合 init_func
  2. 減少資料點:markevery、下採樣、set_data 替換 plot
  3. 避免重建物件:更新現有 Line2D、Text、Collection
  4. 簡化座標軸:固定 xlim/ylim、關閉不必要 grid/legend
  5. 使用 numpy 陣列:避免 Python 列表轉換開銷
  6. 調整 interval:不要低於螢幕重繪率 (通常 16-33ms)
  7. 多進程渲染:大量幀儲存時用 multiprocessing 分割

進階應用:多子圖同步動畫


fig, axes = plt.subplots(2, 1, sharex=True)
lines = [ax.plot([], [])[0] for ax in axes]

def animate(frame):
    for i, (ax, line) in enumerate(zip(axes, lines)):
        x = np.linspace(0, 10, 100)
        y = np.sin(x + frame * 0.1 * (i+1))
        line.set_data(x, y)
        ax.relim()
        ax.autoscale_view()
    return lines

ani = FuncAnimation(fig, animate, frames=200, interval=50, blit=True)

常見問題與解決

問題原因解決
動畫不動/靜止未呼叫 plt.show()、interval 太大、blit=True 但無 init_func檢查 show()、interval、init_func 回傳藝術家
閃爍/殘影blit=False 全畫布重繪、背景未清除啟用 blit=True、確保 init_func 正確
儲存失敗缺少 ffmpeg/imagemagick/pillow安裝對應 writer、或用 to_jshtml()
記憶體洩漏長時間運行累積資料、未清理限制資料長度、定期重置、使用生成器
Jupyter 不顯示需特殊輸出格式用 %matplotlib notebook 或 ani.to_jshtml()

總結

Matplotlib 動畫核心:FuncAnimation(fig, func, frames, interval, blit=True)。五大資料模式:生成器 (串流)、列表 (預載)、幀號 (程式化)、生成器+狀態 (累積)、fargs (固定資料)。關鍵優化:blit=True + init_func + 回傳藝術家序列。掌握四種更新模式、blit 機制、儲存輸出、效能調優,能實現即時監控儀表板、科學模擬視覺化、教學動畫、資料逐步揭示等豐富應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved