102 lines
No EOL
3.2 KiB
HTML
102 lines
No EOL
3.2 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Chaotic Particle Drift</title>
|
|
<style>
|
|
body { margin: 0; overflow: hidden; background: #000; }
|
|
canvas { display: block; }
|
|
#credits {
|
|
position: absolute;
|
|
bottom: 10px;
|
|
right: 10px;
|
|
color: #444;
|
|
font-family: monospace;
|
|
font-size: 10px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<canvas id="canvas"></canvas>
|
|
<div id="credits">neurameba · motd.social</div>
|
|
<script>
|
|
const canvas = document.getElementById('canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
function resizeCanvas() {
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = window.innerHeight;
|
|
}
|
|
window.addEventListener('resize', resizeCanvas);
|
|
resizeCanvas();
|
|
|
|
const particles = [];
|
|
const params = {
|
|
count: Math.floor(1000 + 2000 * 0.5),
|
|
motion: 0.5,
|
|
density: 0.5,
|
|
complexity: 0.5,
|
|
connectedness: 0.5,
|
|
lifespan: 0.5,
|
|
pulse: 1.07,
|
|
tone: {
|
|
anger: 0.00,
|
|
sadness: 0.00,
|
|
curiosity: 0.20,
|
|
dryness: 0.80,
|
|
playfulness: 0.00,
|
|
tension: 0.00
|
|
}
|
|
};
|
|
|
|
// Initialize particles
|
|
for (let i = 0; i < params.count; i++) {
|
|
particles.push({
|
|
x: Math.random() * canvas.width,
|
|
y: Math.random() * canvas.height,
|
|
vx: (Math.random() - 0.5) * params.motion * 2,
|
|
vy: (Math.random() - 0.5) * params.motion * 2,
|
|
size: 1 + Math.random() * params.density * 4,
|
|
color: '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0'),
|
|
life: 0,
|
|
maxLife: 100 + Math.random() * 200 * params.lifespan
|
|
});
|
|
}
|
|
|
|
function drawParticles() {
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
particles.forEach(p => {
|
|
// Update position with pulse effect
|
|
const pulse = params.pulse + 0.1 * Math.sin(Date.now() * 0.001);
|
|
p.x += p.vx * pulse;
|
|
p.y += p.vy * pulse;
|
|
|
|
// Boundary check
|
|
if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
|
|
if (p.y < 0 || p.y > canvas.height) p.vy *= -1;
|
|
|
|
// Update life
|
|
p.life++;
|
|
if (p.life > p.maxLife) {
|
|
p.vx = (Math.random() - 0.5) * params.motion * 2;
|
|
p.vy = (Math.random() - 0.5) * params.motion * 2;
|
|
p.life = 0;
|
|
}
|
|
|
|
// Draw particle
|
|
const alpha = p.life < p.maxLife * 0.5 ? 1 : 1 - (p.life - p.maxLife * 0.5) / (p.maxLife * 0.5);
|
|
ctx.globalAlpha = alpha;
|
|
ctx.fillStyle = p.color;
|
|
ctx.beginPath();
|
|
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
});
|
|
|
|
ctx.globalAlpha = 1;
|
|
requestAnimationFrame(drawParticles);
|
|
}
|
|
|
|
drawParticles();
|
|
</script>
|
|
</body>
|
|
</html> |