Three.js的粒子特效(ts+vue版)
1、效果与技术原理
本案例实现了一个动态三维粒子场系统,具有以下典型特征:
- 空间随机性:5000个粒子在10单位立方体内服从均匀分布
- 视觉混合效果:采用加法混合(Additive Blending)实现光晕叠加
- 透视关系处理:通过sizeAttenuation实现粒子近大远小
- 交互响应:支持轨道控制器视角操作(旋转/缩放)
效果:
核心原理图解:
2、三维场景构初始化
// 1. 场景容器创建
scene = new THREE.Scene();
// 2. 透视相机配置
camera = new THREE.PerspectiveCamera(
75, // FOV视角(人眼约120度)
window.innerWidth / window.innerHeight,
0.1, // 近裁面(避免渲染过近物体)
1000 // 远裁面(避免渲染过远物体)
);
// 3. 渲染器初始化
renderer = new THREE.WebGLRenderer({
canvas: webglCanvas.value,
alpha: true, // 启用透明通道
antialias: true // 开启抗锯齿
});
renderer.setClearColor(0x000000, 0); // 全透明背景
3、构建粒子系统
const count = 5000; // 粒子数量
const positions = new Float32Array(count * 3); // XYZ坐标
const colors = new Float32Array(count * 3); // RGB颜色
for(let i=0; i<count; i++){
// 位置范围[-5,5]
positions[i*3] = (Math.random()-0.5)*10;
positions[i*3+1] = (Math.random()-0.5)*10;
positions[i*3+2] = (Math.random()-0.5)*10;
// 颜色随机生成
colors[i*3] = Math.random(); // R
colors[i*3+1] = Math.random(); // G
colors[i*3+2] = Math.random(); // B
}
particleGeometry.setAttribute(
'position',
new THREE.BufferAttribute(positions, 3)
);
particleGeometry.setAttribute(
'color',
new THREE.BufferAttribute(colors, 3)
);
const particlesMaterial = new THREE.PointsMaterial({
size: 0.1, // 基础粒子尺寸
sizeAttenuation: true, // 启用透视缩放
transparent: true, // 允许透明
alphaMap: particleTexture, // 透明贴图控制形状
depthWrite: false, // 关闭深度缓冲写入
blending: THREE.AdditiveBlending, // 加法混合模式
vertexColors: true // 启用顶点颜色
});
4、交互与可视化进阶
轨道控制器优化:
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用惯性
controls.dampingFactor = 0.05; // 惯性系数
controls.rotateSpeed = 0.5; // 旋转灵敏度
controls.minDistance = 2; // 最近缩放距离
controls.maxDistance = 20; // 最远缩放距离
自适应响应方案:
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); // 必须手动更新
renderer.setSize(window.innerWidth, window.innerHeight);
});
5、常见问题
常见问题 | 可能原因 | 解决方案 |
---|---|---|
粒子显示为黑色 | 未启用顶点颜色 | 检查vertexColors:true配置 |
边缘锯齿严重 | 抗锯齿未开启 | 启用antialias:true |
移动卡顿 | 帧率过高 | 限制最大FPS:requestAnimationFrame节流 |