粒子飘散效果用canvas+JavaScript实现,核心是可控随机初始化位置与速度、阻尼衰减运动、rgba单独设透明度、requestAnimationFrame驱动及半透明覆盖清屏避免闪烁。

粒子飘散效果不依赖 CSS 动画或 Flash,核心是用 canvas + JavaScript 控制每个粒子的初始位置、速度和生命周期;用原生 requestAnimationFrame 驱动更新,比 setInterval 更平滑且节能。
怎么在 canvas 上生成随机飘散的粒子
关键不是“随机”,而是“可控的随机”:每个粒子需独立拥有 x、y、vx(x 方向速度)、vy(y 方向速度)、life(剩余存活帧数)。
- 初始位置通常从某个中心点(如点击位置或元素中心)出发,用
Math.random()在小范围内偏移:x = centerX + (Math.random() - 0.5) * 40 - 初速度建议用极坐标转换:先随机角度
angle = Math.random() * Math.PI * 2,再按速率缩放:vx = Math.cos(angle) * speed,vy = Math.sin(angle) * speed - 避免所有粒子朝同一方向飞——别直接写
vx = Math.random() * 2 - 1,那样容易集中在水平/垂直方向,极坐标更自然
粒子怎么越飞越慢、越变越透明
真实感来自衰减:速度和透明度不能线性归零,否则运动僵硬。推荐每帧对 vx/vy 乘一个阻尼系数(如 0.97),同时用 life 值映射 alpha(透明度):
- 阻尼太强(如
0.9)→ 粒子 20 帧就停住;太弱(0.995)→ 飘太久,视觉上像卡顿 -
alpha = life / maxLife是最简方案,但建议加个缓动:alpha = Math.pow(life / maxLife, 1.5),让消散前半段更慢、后半段更快 - 别用
ctx.globalAlpha全局设透明度——它会影响后续所有绘制;应给每个粒子单独用rgba(r,g,b,alpha)填色
为什么 requestAnimationFrame 里清空 canvas 会闪烁
常见错误是每次动画帧都用 ctx.clearRect(0, 0, width, height) 清全屏,尤其当粒子数量多、设备性能低时,清屏和重绘之间出现视觉间隙,造成闪烁。
立即学习“前端免费学习笔记(深入)”;
-
解决方法一:改用半透明覆盖模拟残影,例如
ctx.fillStyle = 'rgba(255, 255, 255, 0.1)'; ctx.fillRect(0, 0, width, height);—— 这样旧粒子渐隐,新粒子叠加,更接近真实烟雾感 - 解决方法二:只清除粒子上一帧留下的痕迹,需要额外存每个粒子上一帧的
oldX/oldY,然后用小矩形擦除(适合少量粒子) - 注意:若 canvas 设置了
width/height属性(而非 CSS 缩放),清屏范围必须严格匹配 canvas 的实际像素尺寸,否则留白或裁剪
真正难的不是算位置,而是控制粒子密度与帧率的平衡——100 个粒子在低端安卓上可能掉到 30fps,而 20 个又显得单薄;建议加个动态计数器,根据上一帧耗时自动增减粒子数,这个逻辑常被忽略,但直接影响体验是否“跟手”。











