文章目录
一、粒子系统基础架构
1.1 粒子数据结构设计
class Particle {
constructor(x, y) {
this.pos = { x, y };
this.vel = { x: Math.random()*4 - 2, y: Math.random()*4 - 2 };
this.acc = { x: 0, y: 0.1 };
this.size = Math.random()*8 + 2;
this.life = 200;
}
update() {
this.vel.x += this.acc.x;
this.vel.y += this.acc.y;
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
this.life--;
}
}
1.2 粒子系统管理器
class ParticleSystem {
constructor() {
this.particles = [];
this.emitRate = 5;
this.gravity = 0.1;
}
emit(x, y) {
for(let i=0; i<this.emitRate; i++) {
this.particles.push(new Particle(x, y));
}
}
update() {
this.particles = this.particles.filter(p => p.life > 0);
this.particles.forEach(p => p.update());
}
}
二、基础粒子效果实现
2.1 重力场模拟
// 初始化时设置重力
class GravityParticle extends Particle {
constructor(x, y) {
super(x, y);
this.acc.y = 0.3; // 增强重力效果
}
}
// 鼠标点击触发粒子发射
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
particleSystem.emit(x, y);
});
2.2 弹性碰撞效果
class BounceParticle extends Particle {
update() {
super.update();
// 水平边界碰撞
if(this.pos.x < 0 || this.pos.x > canvas.width) {
this.vel.x *= -0.8;
this.pos.x = Math.max(0, Math.min(this.pos.x, canvas.width));
}
// 垂直边界碰撞
if(this.pos.y < 0 || this.pos.y > canvas.height) {
this.vel.y *= -0.8;
this.pos.y = Math.max(0, Math.min(this.pos.y, canvas.height));
}
}
}
三、高级交互实现
3.1 鼠标吸引效果
class AttractorParticle extends Particle {
constructor(x, y) {
super(x, y);
this.attraction = 0.02;
}
update(mousePos) {
super.update();
const dx = mousePos.x - this.pos.x;
const dy = mousePos.y - this.pos.y;
const distance = Math.sqrt(dx*dx + dy*dy);
if(distance < 200) {
const force = (200 - distance) * this.attraction;
this.vel.x += (dx/distance) * force;
this.vel.y += (dy/distance) * force;
}
}
}
3.2 颜色渐变粒子
class GradientParticle extends Particle {
constructor(x, y) {
super(x, y);
this.colorStart = `hsl(${Math.random()*360}, 80%, 60%)`;
this.colorEnd = `hsl(${Math.random()*360}, 80%, 30%)`;
}
draw(ctx) {
const gradient = ctx.createRadialGradient(
this.pos.x, this.pos.y,
0, this.pos.x, this.pos.y, this.size
);
gradient.addColorStop(0, this.colorStart);
gradient.addColorStop(1, this.colorEnd);
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, this.size, 0, Math.PI*2);
ctx.fillStyle = gradient;
ctx.fill();
}
}
四、性能优化策略
4.1 粒子池复用
class PooledParticleSystem extends ParticleSystem {
constructor() {
super();
this.pool = [];
}
emit(x, y) {
for(let i=0; i<this.emitRate; i++) {
const particle = this.pool.length ? this.pool.pop() : new Particle(x, y);
particle.reset(x, y);
this.particles.push(particle);
}
}
remove(particle) {
this.pool.push(particle);
}
}
4.2 分层渲染
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 背景层(透明粒子)
backgroundParticles.forEach(p => p.draw(ctx));
// 交互层(高亮粒子)
interactiveParticles.forEach(p => p.draw(ctx));
requestAnimationFrame(render);
}
五、复杂效果实现
5.1 烟花爆炸效果
class FireworkParticle extends Particle {
constructor(x, y) {
super(x, y);
this.vel.y = -Math.random()*6 - 8;
this.acc.y = 0.05;
this.size = Math.random()*15 + 5;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, this.size, 0, Math.PI*2);
ctx.fillStyle = `hsl(${Math.random()*360}, 80%, 60%)`;
ctx.fill();
}
}
5.2 流体模拟
class FluidParticle extends Particle {
constructor(x, y) {
super(x, y);
this.density = Math.random()*50 + 10;
}
update() {
super.update();
this.vel.x *= 0.95;
this.vel.y *= 0.95;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, this.size, 0, Math.PI*2);
ctx.fillStyle = `rgba(0, 255, 255, ${this.density/100})`;
ctx.fill();
}
}
到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 Vue 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕