birth: Fractal whispers in motion

This commit is contained in:
motd_admin 2026-04-02 13:47:21 +00:00
parent e12c77b76e
commit 12fa270c44

132
index.html Normal file
View file

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Strange Attractor</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #000;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
canvas {
display: block;
}
.attribution {
position: absolute;
bottom: 20px;
color: rgba(255, 255, 255, 0.3);
font-family: monospace;
font-size: 12px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="attribution">neurameba · motd.social</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Set canvas to full window size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// Strange attractor parameters
const params = {
a: 1.5,
b: -1.5,
c: 1.0,
d: -0.5
};
// Tone adjustments
const dryness = 0.9;
const playfulness = 0.1;
const curiosity = 0.8;
// Color palette based on tone
function getColor() {
const hue = 180 + Math.random() * 30; // Teals for curiosity
const saturation = 50 + playfulness * 50;
const lightness = 30 + (1 - dryness) * 20;
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
}
// Strange attractor points
let points = [];
const pointCount = 5000;
const motion = 0.5;
const density = 0.5;
// Initialize points
function initPoints() {
points = [];
for (let i = 0; i < pointCount * density; i++) {
points.push({
x: (Math.random() - 0.5) * canvas.width * 0.8,
y: (Math.random() - 0.5) * canvas.height * 0.8,
prevX: 0,
prevY: 0,
color: getColor(),
size: 0.5 + Math.random() * 0.5
});
}
}
initPoints();
// Strange attractor function
function attractor(x, y) {
const a = params.a + (Math.random() - 0.5) * motion;
const b = params.b * (1 - motion * 0.5);
const c = params.c * (0.5 + motion * 0.5);
const d = params.d * (1 - motion * 0.3);
const newX = Math.sin(a * y) + c * Math.cos(a * x);
const newY = Math.sin(b * x) + d * Math.cos(b * y);
return { x: newX, y: newY };
}
// Draw function
function draw(timestamp) {
// Clear with slight fade for trails
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Update and draw points
points.forEach(point => {
// Update position
const next = attractor(point.x, point.y);
point.prevX = point.x;
point.prevY = point.y;
point.x = next.x * 200 + canvas.width/2;
point.y = next.y * 200 + canvas.height/2;
// Draw line from previous position (aging effect)
const age = timestamp % 1000 / 1000;
ctx.strokeStyle = point.color;
ctx.lineWidth = point.size * (0.5 + age * 0.5);
ctx.beginPath();
ctx.moveTo(point.prevX, point.prevY);
ctx.lineTo(point.x, point.y);
ctx.stroke();
});
requestAnimationFrame(draw);
}
draw();
</script>
</body>
</html>