前端圈在传的粒子特效,鼠标一过图片就散了,原来是这样做的
Particles Playground 是一个基于 Three.js 和自定义 GLSL 着色器的粒子特效库。它的核心能力是:把一张普通图片(或视频帧)转换为由成千上万个粒子组成的动态画面,并响应鼠标或触摸操作,在光标经过的地方留下拖尾效果。
这类效果在前端开发里并不罕见,但大多数实现要么依赖纯 JavaScript 逐帧计算粒子位置(性能开销大),要么视觉效果比较简陋。Particles Playground 的思路有所不同——它以图片纹理作为粒子颜色的来源,用 GLSL 着色器在 GPU 上完成粒子的位置计算和噪声扰动,同时引入 GSAP 处理场景切换动画,整体在视觉质量和性能之间取得了比较好的平衡。

效果是如何实现的
理解这个项目,需要先了解它的技术路径:
纹理采样决定粒子颜色
传统粒子系统里,每个粒子的颜色通常是单独设定的。Particles Playground 的做法是把目标图片作为 WebGL 纹理传入着色器,每个粒子根据自己的 UV 坐标从图片上采样颜色,因此粒子聚合后还原的是图片本身的内容。
GLSL 2D Simplex Noise 驱动粒子运动
粒子在静止状态下并非完全固定,而是通过 GLSL 实现的 2D Simplex 噪声(由 Ian McEwan 编写)不断产生轻微扰动,形成粒子"呼吸"的动态感。
鼠标拖尾通过 buildTail() 实现
鼠标移动时,buildTail() 方法会在光标经过的 UV 坐标位置写入影响力数据,着色器读取这个数据后,对附近的粒子施加额外偏移,形成粒子被"推开"然后缓慢归位的拖尾效果。
性能控制
库内置了 FPS 上限控制和鼠标事件节流,避免在高刷新率设备上造成不必要的 GPU 开销。抗锯齿也是按条件开启的,低端设备上会自动关闭。
配置参数说明
每个场景通过一个配置对象定义,主要参数如下:
| 参数 | 类型 | 说明 |
|---|---|---|
url | string | 图片或视频的路径 |
threshold | number | 像素灰度阈值,控制哪些区域生成粒子 |
random | number | 粒子随机偏移强度,值越大粒子分布越松散 |
depth | number | 深度效果强度,影响粒子 Z 轴偏移 |
maxDepth | number | 最大深度值 |
size | number | 粒子大小 |
square | number | 粒子形状:0 = 圆形,1 = 正方形 |
quote | string | 场景附带的文字内容 |
texture | string | 设为 "video" 时使用视频纹理,否则为图片 |
threshold 是控制效果密度的关键参数:值越低,粒子越密集,近似还原图片原貌;值越高,只有亮度超过阈值的区域才生成粒子,画面会更稀疏、抽象。
安装与使用
前提条件:需要在 Node.js 环境下使用,并通过 Vite 启动开发服务器。
安装
git clone https://github.com/isladjan/particles-playground.git
cd particles-playground
npm install启动开发服务器
npx vite如果需要在局域网内其他设备(如手机)上预览触摸交互效果:
npx vite --host构建生产版本
npx vite build
npx vite preview # 预览构建结果集成到自己的项目
核心 API 只有两步:实例化 Effect 类,然后调用 init()。
基础用法
import { Effect } from './effect.js';
const texturesOptions = [
{
url: './images/photo1.jpg',
threshold: 0.1,
random: 0.5,
depth: 1.2,
maxDepth: 2.0,
size: 2,
square: 0, // 圆形粒子
quote: '这里是场景文字',
},
{
url: './images/photo2.jpg',
threshold: 0.2,
random: 0.8,
depth: 0.8,
maxDepth: 1.5,
size: 1.5,
square: 1, // 正方形粒子
quote: '第二个场景',
},
];
const effect = new Effect(texturesOptions);
effect.init();使用视频纹理
把视频帧作为粒子颜色来源时,设置 texture: 'video':
{
url: './videos/clip.mp4',
texture: 'video',
threshold: 0.15,
random: 0.6,
depth: 1.0,
maxDepth: 1.8,
size: 2,
square: 0,
}切换场景
项目内置 changeTexture(direction) 方法,传入方向值可以在多个场景之间切换,场景切换动画由 GSAP 驱动:
// 切换到下一个场景
effect.changeTexture(1);
// 切换到上一个场景
effect.changeTexture(-1);适合哪些场景
Particles Playground 比较适合以下使用场景:
- 创意型落地页:把主视觉图片或品牌形象转化为粒子效果,作为页面首屏
- 作品集展示:将作品截图以粒子形式呈现,增加视觉层次
- 互动艺术装置:结合触摸屏,配合
--host参数在大屏设备上展示
需要注意的是,WebGL 依赖浏览器和硬件支持,在部分低端移动设备上性能表现可能不理想。库本身提供了 FPS 限制和节流机制,但对于非常低端的设备,可能还需要进一步降低粒子数量或关闭深度效果。此外,由于粒子效果基于图片纹理,图片分辨率和 threshold 的搭配需要多次调试才能达到预期效果。
写在最后
Particles Playground 的实现思路值得关注的地方在于:它没有在 JavaScript 层面逐帧计算每个粒子的位置,而是把这部分计算交给 GPU 的着色器完成,同时用视频/图片纹理承担了粒子着色的任务,减少了 CPU 的工作量。这个架构思路对于需要大量粒子的场景有比较明显的优势。
项目代码量不大,effect.js 是核心文件,对 Three.js 和 GLSL 有一定了解的开发者可以直接阅读源码理解实现原理,或者在此基础上扩展自己的交互逻辑。
GitHub 项目地址:https://github.com/isladjan/particles-playground (opens in a new tab)