carrot_animation / assets /js /particles.js
ivanfioravanti's picture
Upload folder using huggingface_hub
24bc5c4 verified
const canvas = document.getElementById('particleCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Configuration
let config = {
particleCount: 100,
particleSize: 2,
speed: 1,
connectionDistance: 100,
colorMode: 'rainbow',
mouseEffect: 'attract',
mouseRadius: 150
};
// Mouse position
let mouse = {
x: canvas.width / 2,
y: canvas.height / 2
};
// Particles array
let particles = [];
// Color modes
const colorModes = {
rainbow: (particle, time) => {
const hue = (time * 0.1 + particle.id * 10) % 360;
return `hsl(${hue}, 70%, 50%)`;
},
ocean: (particle, time) => {
const hue = 180 + Math.sin(time * 0.001 + particle.id * 0.1) * 60;
return `hsl(${hue}, 70%, 50%)`;
},
fire: (particle, time) => {
const hue = Math.sin(time * 0.001 + particle.id * 0.1) * 30;
return `hsl(${hue}, 80%, 50%)`;
},
monochrome: (particle, time) => {
const brightness = 30 + Math.sin(time * 0.001 + particle.id * 0.1) * 20;
return `hsl(0, 0%, ${brightness}%)`;
},
neon: (particle, time) => {
const colors = ['#ff00ff', '#00ffff', '#ffff00', '#ff00aa'];
return colors[Math.floor((time * 0.001 + particle.id * 0.1) % colors.length)];
}
};
// Particle class
class Particle {
constructor(id) {
this.id = id;
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.vx = (Math.random() - 0.5) * config.speed;
this.vy = (Math.random() - 0.5) * config.speed;
this.size = config.particleSize;
this.baseSize = config.particleSize;
}
update() {
// Mouse interaction
const dx = mouse.x - this.x;
const dy = mouse.y - this.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < config.mouseRadius) {
const force = (1 - distance / config.mouseRadius) * 0.5;
if (config.mouseEffect === 'attract') {
this.vx += dx * force * 0.01;
this.vy += dy * force * 0.01;
} else {
this.vx -= dx * force * 0.01;
this.vy -= dy * force * 0.01;
}
}
// Update position
this.x += this.vx * config.speed;
this.y += this.vy * config.speed;
// Bounce off walls
if (this.x < 0 || this.x > canvas.width) {
this.vx *= -0.9;
this.x = Math.max(0, Math.min(canvas.width, this.x));
}
if (this.y < 0 || this.y > canvas.height) {
this.vy *= -0.9;
this.y = Math.max(0, Math.min(canvas.height, this.y));
}
// Apply friction
this.vx *= 0.99;
this.vy *= 0.99;
// Size animation
this.size = this.baseSize + Math.sin(Date.now() * 0.001 + this.id) * 0.5;
}
draw(time) {
ctx.fillStyle = colorModes[config.colorMode](this, time);
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
// Glow effect
ctx.shadowBlur = 10;
ctx.shadowColor = colorModes[config.colorMode](this, time);
ctx.fill();
ctx.shadowBlur = 0;
}
}
// Initialize particles
function initParticles() {
particles = [];
for (let i = 0; i < config.particleCount; i++) {
particles.push(new Particle(i));
}
}
// Draw connections between particles
function drawConnections() {
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x - particles[j].x;
const dy = particles[i].y - particles[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < config.connectionDistance) {
const opacity = 1 - distance / config.connectionDistance;
ctx.strokeStyle = `rgba(100, 255, 218, ${opacity * 0.2})`;
ctx.lineWidth = opacity * 0.5;
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.stroke();
}
}
}
}
// Animation loop
function animate() {
ctx.fillStyle = 'rgba(10, 10, 10, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const time = Date.now();
// Update and draw particles
particles.forEach(particle => {
particle.update();
particle.draw(time);
});
// Draw connections
drawConnections();
requestAnimationFrame(animate);
}
// Event listeners
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
canvas.addEventListener('mousemove', (e) => {
mouse.x = e.clientX;
mouse.y = e.clientY;
});
canvas.addEventListener('click', (e) => {
// Create explosion effect
for (let i = 0; i < 20; i++) {
const angle = (Math.PI * 2 * i) / 20;
const speed = 5 + Math.random() * 5;
const particle = new Particle(particles.length);
particle.x = e.clientX;
particle.y = e.clientY;
particle.vx = Math.cos(angle) * speed;
particle.vy = Math.sin(angle) * speed;
particle.baseSize = 3 + Math.random() * 2;
particles.push(particle);
}
// Remove excess particles
if (particles.length > config.particleCount * 2) {
particles.splice(0, particles.length - config.particleCount);
}
});
// Keyboard controls
document.addEventListener('keydown', (e) => {
switch(e.key.toLowerCase()) {
case ' ':
e.preventDefault();
const modes = Object.keys(colorModes);
const currentIndex = modes.indexOf(config.colorMode);
config.colorMode = modes[(currentIndex + 1) % modes.length];
break;
case '1':
config.particleCount = 50;
initParticles();
break;
case '2':
config.particleCount = 100;
initParticles();
break;
case '3':
config.particleCount = 200;
initParticles();
break;
case '4':
config.particleCount = 300;
initParticles();
break;
case '5':
config.particleCount = 500;
initParticles();
break;
case 'q':
config.speed = Math.max(0.1, config.speed - 0.1);
break;
case 'w':
config.speed = Math.min(5, config.speed + 0.1);
break;
case 'a':
config.particleSize = Math.max(1, config.particleSize - 0.5);
particles.forEach(p => p.baseSize = config.particleSize);
break;
case 's':
config.particleSize = Math.min(10, config.particleSize + 0.5);
particles.forEach(p => p.baseSize = config.particleSize);
break;
case 'z':
config.connectionDistance = Math.max(50, config.connectionDistance - 10);
break;
case 'x':
config.connectionDistance = Math.min(300, config.connectionDistance + 10);
break;
case 'r':
config = {
particleCount: 100,
particleSize: 2,
speed: 1,
connectionDistance: 100,
colorMode: 'rainbow',
mouseEffect: 'attract',
mouseRadius: 150
};
initParticles();
break;
case 'm':
config.mouseEffect = config.mouseEffect === 'attract' ? 'repel' : 'attract';
break;
}
});
// Initialize and start
initParticles();
animate();