本文目录导读:

我来分享几种用Matplotlib制作动画的常用方法,从简单到复杂。
基础动画:FuncAnimation(最常用)
示例1:正弦波动画
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 创建图形
fig, ax = plt.subplots()
x = np.linspace(0, 2*np.pi, 100)
line, = ax.plot(x, np.sin(x), 'b-', linewidth=2)
# 设置坐标轴
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1.5, 1.5)
ax.grid(True, alpha=0.3)
# 动画更新函数
def update(frame):
line.set_ydata(np.sin(x + frame/10)) # 更新y数据
ax.set_title(f'正弦波动画 - 帧: {frame}')
return line,
# 创建动画
ani = FuncAnimation(fig, update, frames=100, interval=50, blit=True)
# 显示动画
plt.show()
# 保存动画(可选)
# ani.save('sine_wave.gif', writer='pillow', fps=20)
示例2:散点图动态更新
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 准备数据
np.random.seed(42)
n_points = 50
x = np.random.randn(n_points)
y = np.random.randn(n_points)
colors = np.random.rand(n_points)
sizes = np.random.randint(50, 200, n_points)
fig, ax = plt.subplots(figsize=(8, 6))
scatter = ax.scatter(x, y, c=colors, s=sizes, alpha=0.6)
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
ax.grid(True, alpha=0.3)
ax.set_title('动态散点图')
def update(frame):
# 更新数据点位置
new_x = x + np.random.randn(n_points) * 0.1
new_y = y + np.random.randn(n_points) * 0.1
scatter.set_offsets(np.c_[new_x, new_y])
scatter.set_sizes(sizes + np.random.randint(-10, 10, n_points))
ax.set_title(f'动态散点图 - 帧: {frame}')
return scatter,
ani = FuncAnimation(fig, update, frames=100, interval=100, blit=True)
plt.show()
3D动画
示例3:3D曲面动画
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from mpl_toolkits.mplot3d import Axes3D
# 创建3D图形
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 生成数据网格
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
# 初始Z值
Z = np.sin(np.sqrt(X**2 + Y**2))
# 绘制初始曲面
surf = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
def update(frame):
ax.clear()
# 动态变化的曲面
Z = np.sin(np.sqrt(X**2 + Y**2) + frame/10) * (1 + 0.1*np.sin(frame/5))
# 重绘
surf = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.set_zlim(-1.5, 1.5)
ax.set_title(f'3D曲面动画 - 帧: {frame}')
return surf,
ani = FuncAnimation(fig, update, frames=100, interval=50)
plt.show()
复杂案例:物理模拟
示例4:粒子系统动画
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class Particle:
def __init__(self, x, y, vx, vy, color, size):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
self.color = color
self.size = size
def update(self, dt=0.1):
# 简单物理模拟
self.x += self.vx * dt
self.y += self.vy * dt
# 边界碰撞
if abs(self.x) > 5:
self.vx *= -1
if abs(self.y) > 5:
self.vy *= -1
# 创建粒子
np.random.seed(42)
n_particles = 30
particles = []
for _ in range(n_particles):
particles.append(Particle(
x=np.random.uniform(-4, 4),
y=np.random.uniform(-4, 4),
vx=np.random.uniform(-2, 2),
vy=np.random.uniform(-2, 2),
color=np.random.rand(3),
size=np.random.uniform(20, 80)
))
# 创建图形
fig, ax = plt.subplots(figsize=(8, 8))
scatter = ax.scatter([], [], c=[], s=[])
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.grid(True, alpha=0.3)
ax.set_aspect('equal')
def update(frame):
# 更新所有粒子位置
for p in particles:
p.update()
# 更新散点图数据
x_data = [p.x for p in particles]
y_data = [p.y for p in particles]
colors = [p.color for p in particles]
sizes = [p.size for p in particles]
scatter.set_offsets(np.c_[x_data, y_data])
scatter.set_color(colors)
scatter.set_sizes(sizes)
ax.set_title(f'粒子系统模拟 - 帧: {frame}')
return scatter,
ani = FuncAnimation(fig, update, frames=200, interval=50, blit=True)
plt.show()
高级技巧
示例5:多子图同步动画
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 创建多个子图
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
ax1, ax2, ax3, ax4 = axes.flatten()
# 初始化数据
t = np.linspace(0, 2*np.pi, 100)
line1, = ax1.plot(t, np.sin(t), 'r-', linewidth=2)
line2, = ax2.plot(t, np.cos(t), 'b-', linewidth=2)
line3, = ax3.plot(t, np.sin(t), 'g-', linewidth=2)
scatter = ax4.scatter([], [], c=[], s=[])
# 设置坐标轴
for ax in [ax1, ax2, ax3, ax4]:
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1.5, 1.5)
ax.grid(True, alpha=0.3)
ax4.set_title('散点图')
ax1.set_title('正弦波')
ax2.set_title('余弦波')
ax3.set_title('正弦波')
def update(frame):
phase = frame / 20
# 更新线条
line1.set_ydata(np.sin(t + phase))
line2.set_ydata(np.cos(t + phase))
line3.set_ydata(np.sin(t + 2*phase))
# 更新散点图
x_data = np.cos(t + phase)
y_data = np.sin(t + phase)
scatter.set_offsets(np.c_[x_data[::5], y_data[::5]])
scatter.set_color(np.random.rand(20, 3))
return line1, line2, line3, scatter,
ani = FuncAnimation(fig, update, frames=200, interval=30, blit=True)
plt.tight_layout()
plt.show()
实用技巧总结
保存动画
# 保存为GIF
ani.save('animation.gif', writer='pillow', fps=20)
# 保存为MP4(需要ffmpeg)
ani.save('animation.mp4', writer='ffmpeg', fps=20)
# 保存为HTML5视频(在Jupyter中)
from IPython.display import HTML
HTML(ani.to_html5_video())
性能优化
# 1. 使用blit=True减少重绘 ani = FuncAnimation(fig, update, frames=100, interval=50, blit=True) # 2. 减少数据点数量 x = np.linspace(0, 2*np.pi, 50) # 而不是1000 # 3. 使用更简单的图形元素 # 首选:Line2D, Scatter # 避免:填充区域、等高线
常见问题解决
# 1. 动画不显示 plt.ion() # 打开交互模式 # 2. 内存泄露 ani.event_source.stop() # 停止动画 # 3. 调整帧率 # interval=50 表示50毫秒一帧,即20fps ani = FuncAnimation(fig, update, frames=100, interval=50)
这些案例覆盖了Matplotlib动画的主要应用场景,开始学习时推荐从FuncAnimation和简单的一维动画入手,逐步扩展到复杂应用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播