js实现3D烟花特效
实现3D烟花特效的方法
使用Three.js库可以高效实现3D烟花效果。Three.js是一个基于WebGL的JavaScript 3D图形库,适合创建复杂的3D动画效果。
基础环境搭建
引入Three.js库并初始化基础场景:
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
烟花粒子系统实现
创建烟花爆炸时的粒子系统:
function createFirework(position) {
const particles = 1000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particles * 3);
for (let i = 0; i < particles; i++) {
const i3 = i * 3;
positions[i3] = position.x;
positions[i3 + 1] = position.y;
positions[i3 + 2] = position.z;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: new THREE.Color(Math.random(), Math.random(), Math.random()),
size: 0.2,
blending: THREE.AdditiveBlending,
transparent: true
});
const particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
return { particleSystem, positions };
}
动画更新逻辑
实现粒子爆炸和下落动画:
function animateFirework(firework) {
const { particleSystem, positions } = firework;
const geometry = particleSystem.geometry;
const positionAttribute = geometry.attributes.position;
for (let i = 0; i < positionAttribute.count; i++) {
const i3 = i * 3;
positionAttribute.array[i3] += (Math.random() - 0.5) * 0.5;
positionAttribute.array[i3 + 1] += (Math.random() - 0.5) * 0.5;
positionAttribute.array[i3 + 2] += (Math.random() - 0.5) * 0.5;
// 模拟重力
positionAttribute.array[i3 + 1] -= 0.01;
}
positionAttribute.needsUpdate = true;
// 淡出效果
particleSystem.material.opacity -= 0.005;
if (particleSystem.material.opacity <= 0) {
scene.remove(particleSystem);
return false;
}
return true;
}
主渲染循环
整合所有元素到主动画循环:
const fireworks = [];
let lastFireworkTime = 0;
function animate() {
requestAnimationFrame(animate);
const currentTime = Date.now();
if (currentTime - lastFireworkTime > 1000) {
const position = new THREE.Vector3(
(Math.random() - 0.5) * 10,
0,
(Math.random() - 0.5) * 10
);
fireworks.push(createFirework(position));
lastFireworkTime = currentTime;
}
for (let i = fireworks.length - 1; i >= 0; i--) {
if (!animateFirework(fireworks[i])) {
fireworks.splice(i, 1);
}
}
renderer.render(scene, camera);
}
animate();
性能优化技巧
使用InstancedMesh代替Points可以提升性能:
const particleCount = 10000;
const instancedMesh = new THREE.InstancedMesh(
new THREE.SphereGeometry(0.1, 8, 8),
new THREE.MeshBasicMaterial({ color: 0xffffff }),
particleCount
);
const dummy = new THREE.Object3D();
for (let i = 0; i < particleCount; i++) {
dummy.position.set(Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5);
dummy.updateMatrix();
instancedMesh.setMatrixAt(i, dummy.matrix);
}
scene.add(instancedMesh);
视觉效果增强
添加辉光效果提升视觉冲击力:
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
const bloomPass = new UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
1.5, 0.4, 0.85
);
bloomPass.threshold = 0;
bloomPass.strength = 1.5;
bloomPass.radius = 0.5;
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
composer.addPass(bloomPass);
// 在animate函数中使用composer.render()代替renderer.render()






