炫酷粒子系统动画实战:Matplotlib实现银河漩涡效果
效果演示:银河粒子漩涡
动态特征:
- 500个粒子组成旋转星云,呈现螺旋轨迹运动
- 粒子颜色随速度渐变(蓝->紫->红)
- 粒子尺寸根据离心力动态变化
- 背景呈现深空渐变效果


核心代码分析
1. 粒子系统初始化
class ParticleSystem:
def __init__(self, n=500):
# 极坐标参数初始化
self.theta = np.linspace(0, 8*np.pi, n)
self.r = np.linspace(0, 1, n)**0.5 # 半径非线性分布
# 动态参数
self.dr = np.random.uniform(0.95, 1.05, n) # 半径变化因子
self.speed = np.random.uniform(0.8, 1.2, n) # 角速度差异
self.size = 10 * np.sin(self.theta)**2 + 1 # 初始尺寸
# 转换为笛卡尔坐标
self.x = self.r * np.cos(self.theta)
self.y = self.r * np.sin(self.theta)
关键技术点:
- 使用极坐标构建初始分布,r**0.5实现中心密集效果
- speed参数控制粒子角速度差异,产生层次感
- sin(theta)^2尺寸计算创建波浪形大小分布
2. 动画更新函数
def update(frame):
# 半径动态变化(模拟离心力)
ps.r *= ps.dr
ps.r = np.clip(ps.r, 0, 2) # 限制最大半径
# 角度持续增加(形成旋转)
ps.theta += 0.02 * ps.speed
# 坐标更新
ps.x = ps.r * np.cos(ps.theta)
ps.y = ps.r * np.sin(ps.theta)
# 颜色和尺寸更新
colors = plt.cm.plasma((ps.r/2 + frame/100) % 1) # 动态色相
sizes = 50 * np.abs(np.sin(0.5*ps.theta + frame/20)) + 1
# 更新散点图属性
scatter.set_offsets(np.c_[ps.x, ps.y])
scatter.set_color(colors)
scatter.set_sizes(sizes)
return scatter,
核心算法:
- clip函数限制粒子扩散范围
- plasma颜色映射结合帧数实现动态渐变
- set_offsets高效更新所有粒子位置(比逐点更新快10倍+)
3. 渲染优化技巧
# 使用TkAgg后端提升性能
import matplotlib
matplotlib.use('TkAgg')
# 创建深空渐变背景
gradient = np.linspace(0, 1, 256).reshape(1, -1)
ax.imshow(gradient, aspect='auto', cmap='plasma',
extent=[-2.5, 2.5, -2.5, 2.5], alpha=0.15)
# 开启blitting加速
ani = animation.FuncAnimation(fig, update, interval=20,
blit=True, cache_frame_data=False)
性能优化:
- TkAgg后端支持硬件加速
- imshow创建静态渐变背景,减少重复渲染
- cache_frame_data=False避免内存泄漏
完整实现代码
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.colors import Normalize
class ParticleSystem:
def __init__(self, n=500):
self.theta = np.linspace(0, 8*np.pi, n)
self.r = np.linspace(0, 1, n)**0.5
self.dr = np.random.uniform(0.95, 1.05, n)
self.speed = np.random.uniform(0.8, 1.2, n)
self.size = 10 * np.sin(self.theta)**2 + 1
self.x = self.r * np.cos(self.theta)
self.y = self.r * np.sin(self.theta)
# 初始化画布
fig, ax = plt.subplots(figsize=(8,8), facecolor='black')
ax.axis('off')
ax.set_xlim(-2.5, 2.5)
ax.set_ylim(-2.5, 2.5)
# 创建渐变背景
gradient = np.linspace(0, 1, 256).reshape(1, -1)
ax.imshow(gradient, aspect='auto', cmap='plasma',
extent=[-2.5, 2.5, -2.5, 2.5], alpha=0.15)
# 初始化粒子系统
ps = ParticleSystem()
scatter = ax.scatter(ps.x, ps.y, c=ps.r, cmap='plasma',
s=ps.size, alpha=0.7, edgecolors='none')
def update(frame):
ps.r = np.clip(ps.r * ps.dr, 0, 2)
ps.theta += 0.02 * ps.speed
ps.x = ps.r * np.cos(ps.theta)
ps.y = ps.r * np.sin(ps.theta)
colors = plt.cm.plasma((ps.r/2 + frame/100) % 1)
sizes = 50 * np.abs(np.sin(0.5*ps.theta + frame/20)) + 1
scatter.set_offsets(np.c_[ps.x, ps.y])
scatter.set_color(colors)
scatter.set_sizes(sizes)
return scatter,
# 运行动画
ani = animation.FuncAnimation(fig, update, frames=200,
interval=20, blit=True, cache_frame_data=False)
# 保存动画(可选)
# ani.save('galaxy.mp4', writer='ffmpeg', dpi=120, extra_args=['-vcodec', 'libx264'])
plt.show()
Matplotlib的动画模块介绍
模块名:matplotlib.animation
作用:生成动态可视化,支持保存为GIF、视频或实时交互显示。
核心类对比
| 类名 | 适用场景 | 核心机制 | 优点 | 缺点 |
|---|---|---|---|---|
| FuncAnimation | 动态生成帧(逐帧更新) | 通过函数回调更新图形元素 | 内存高效,适合复杂动画 | 需要手动编写更新逻辑 |
| ArtistAnimation | 预渲染所有帧后播放 | 直接绘制预先生成的艺术家对象 | 简单易用,适合静态帧序列 | 内存占用高,不适合大数据 |
核心功能分点
FuncAnimation 主要参数
-
fig: 画布对象
-
func: 更新图形的回调函数(每帧调用)
-
frames: 帧数据(可迭代对象或生成器)
-
init_func: 初始化函数(可选)
-
interval: 帧间隔时间(毫秒,默认200)
-
blit: 是否启用优化渲染(仅重绘变化部分)
ArtistAnimation 主要参数
-
fig: 画布对象
-
artists: 包含每帧艺术家对象(如线条、图像)的列表
注意事项
依赖项:
- 保存视频需安装外部库(如ffmpeg或imagemagick)
- 在Jupyter中显示动画需添加%matplotlib notebook或使用HTML(anim.to_html5_video())
性能优化:
- 启用blit=True可显著提升渲染速度
- 避免在回调函数中重复创建对象

1292

被折叠的 条评论
为什么被折叠?



