class ParticleSystem {
constructor(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.particles = [];
this.mouse = { x: 0, y: 0, radius: 100 };
this.gravity = false;
this.colorSchemes = [
['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#ffeaa7'],
['#667eea', '#764ba2', '#f093fb', '#f5576c', '#4facfe'],
['#43e97b', '#38f9d7', '#667eea', '#764ba2', '#f093fb']
];
this.currentScheme = 0;
this.colors = this.colorSchemes[this.currentScheme];
this.resize();
this.init();
this.bindEvents();
this.animate();
}
resize() {
this.canvas.width = this.canvas.offsetWidth;
this.canvas.height = this.canvas.offsetHeight;
}
init() {
this.particles = [];
const particleCount = Math.min(120, Math.floor(this.canvas.width * this.canvas.height / 8000));
for (let i = 0; i < particleCount; i++) {
this.particles.push({
x: Math.random() * this.canvas.width,
y: Math.random() * this.canvas.height,
vx: (Math.random() - 0.5) * 2,
vy: (Math.random() - 0.5) * 2,
size: Math.random() * 4 + 1,
color: this.colors[Math.floor(Math.random() * this.colors.length)],
alpha: Math.random() * 0.6 + 0.4,
originalAlpha: Math.random() * 0.6 + 0.4
});
}
}
bindEvents() {
this.canvas.addEventListener('mousemove', (e) => {
const rect = this.canvas.getBoundingClientRect();
this.mouse.x = e.clientX - rect.left;
this.mouse.y = e.clientY - rect.top;
});
this.canvas.addEventListener('mouseleave', () => {
this.mouse.x = -1000;
this.mouse.y = -1000;
});
window.addEventListener('resize', () => {
this.resize();
this.init();
});
document.getElementById('resetBtn').addEventListener('click', () => {
this.init();
});
document.getElementById('gravityBtn').addEventListener('click', () => {
this.gravity = !this.gravity;
});
document.getElementById('colorBtn').addEventListener('click', () => {
this.currentScheme = (this.currentScheme + 1) % this.colorSchemes.length;
this.colors = this.colorSchemes[this.currentScheme];
this.particles.forEach(particle => {
particle.color = this.colors[Math.floor(Math.random() * this.colors.length)];
});
});
}
update() {
this.particles.forEach(particle => {
// Mouse interaction
const dx = this.mouse.x - particle.x;
const dy = this.mouse.y - particle.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.mouse.radius) {
const force = (this.mouse.radius - distance) / this.mouse.radius;
const angle = Math.atan2(dy, dx);
particle.vx -= Math.cos(angle) * force * 0.5;
particle.vy -= Math.sin(angle) * force * 0.5;
particle.alpha = Math.min(1, particle.originalAlpha + force * 0.5);
} else {
particle.alpha = particle.originalAlpha;
}
// Gravity effect
if (this.gravity) {
particle.vy += 0.1;
}
// Update position
particle.x += particle.vx;
particle.y += particle.vy;
// Friction
particle.vx *= 0.99;
particle.vy *= 0.99;
// Boundary collision
if (particle.x < 0 || particle.x > this.canvas.width) {
particle.vx *= -0.8;
particle.x = Math.max(0, Math.min(this.canvas.width, particle.x));
}
if (particle.y < 0 || particle.y > this.canvas.height) {
particle.vy *= -0.8;
particle.y = Math.max(0, Math.min(this.canvas.height, particle.y));
}
});
}
draw() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// Draw connections
this.particles.forEach((particle, i) => {
for (let j = i + 1; j < this.particles.length; j++) {
const other = this.particles[j];
const dx = particle.x - other.x;
const dy = particle.y - other.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
this.ctx.beginPath();
this.ctx.strokeStyle = `rgba(255, 255, 255, \${(1 - distance / 100) * 0.2})`;
this.ctx.lineWidth = 1;
this.ctx.moveTo(particle.x, particle.y);
this.ctx.lineTo(other.x, other.y);
this.ctx.stroke();
}
}
});
// Draw particles
this.particles.forEach(particle => {
this.ctx.beginPath();
this.ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
this.ctx.fillStyle = particle.color.replace('rgb', 'rgba').replace(')', `, \${particle.alpha})`);
this.ctx.fill();
// Add glow effect
this.ctx.shadowColor = particle.color;
this.ctx.shadowBlur = 10;
this.ctx.fill();
this.ctx.shadowBlur = 0;
});
}
animate() {
this.update();
this.draw();
requestAnimationFrame(() => this.animate());
}
}
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('particleCanvas');
if (canvas) {
new ParticleSystem(canvas);
}
});