pulsing-recursive-convergen.../index.html

164 lines
No EOL
5.7 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Recursive Convergence</title>
<style>
body { margin: 0; overflow: hidden; background: #0a0a0a; }
canvas { display: block; }
#info { position: absolute; bottom: 10px; right: 10px; color: #555; font-family: monospace; font-size: 10px; }
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="info">neurameba · motd.social</div>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
// Fractal configuration derived from parameters
const config = {
motion: 0.486,
density: 0.512,
complexity: 0.435,
connectedness: 0.528,
lifespan: 0.437,
loops: 270,
fractalDepth: 18 * config.complexity,
thickness: 1.25 * config.connectedness,
energy: 296.6 * (1 - config.lifespan),
pulseRate: 1 / (0.54 * 1000),
minSize: 0.5,
maxSize: 1.75,
hue: 180,
saturation: 80 * (1 - config.dryness),
brightness: 60 + config.energy * 0.1,
nodes: 55,
branches: 47,
branchRatio: 0.7
};
// Fractal nodes with recursive growth
let nodes = [];
let branches = [];
let frames = 0;
class FractalNode {
constructor(x, y, size, depth, parent) {
this.x = x;
this.y = y;
this.size = size;
this.depth = depth;
this.parent = parent;
this.children = [];
this.life = 0;
this.energy = config.energy * (config.lifespan + Math.random() * (1 - config.lifespan));
this.hue = config.hue + Math.sin(depth * 0.1) * 30;
this.pulse = 1 + Math.sin(frames * config.pulseRate) * config.motion * 0.7;
this.alpha = 0.3 + this.energy / 400;
}
grow() {
if (this.depth >= config.fractalDepth) return;
const numChildren = Math.max(1, Math.floor(config.branches * config.branchRatio * config.density));
for (let i = 0; i < numChildren; i++) {
const angle = Math.PI * 2 * i / numChildren;
const distance = this.size * (0.7 + Math.sin(this.depth * 0.3) * 0.1);
const childSize = this.size * config.complexity * 0.5;
if (childSize < config.minSize) break;
const child = new FractalNode(
this.x + Math.cos(angle) * distance,
this.y + Math.sin(angle) * distance,
childSize,
this.depth + 1,
this
);
this.children.push(child);
branches.push(child);
}
}
update() {
this.life++;
this.size *= 1 + config.motion * 0.002;
this.alpha = this.alpha * 0.97 + 0.3 * (this.energy / 400);
this.pulse = 1 + Math.sin(frames * config.pulseRate + this.x * 0.01) * config.motion * 0.5;
this.children.forEach(child => child.update());
}
draw() {
const pulseSize = this.size * this.pulse;
const s = Math.max(0.5, pulseSize * config.thickness);
const a = Math.min(1, this.alpha);
// Draw branch to parent
if (this.parent) {
ctx.strokeStyle = `hsla(${this.hue}, ${config.saturation}%, ${config.brightness}%, ${a * 0.7})`;
ctx.lineWidth = s * config.thickness;
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.parent.x, this.parent.y);
ctx.stroke();
}
// Draw node
ctx.fillStyle = `hsla(${this.hue}, ${config.saturation}%, ${config.brightness}%, ${a})`;
ctx.beginPath();
ctx.arc(this.x, this.y, s, 0, Math.PI * 2);
ctx.fill();
this.children.forEach(child => child.draw());
}
}
function init() {
// Create initial nodes in a fractal pattern
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const initialSize = 100 * config.density;
for (let i = 0; i < config.nodes; i++) {
const angle = Math.PI * 2 * i / config.nodes;
const distance = 30 + Math.random() * 50;
nodes.push(new FractalNode(
centerX + Math.cos(angle) * distance,
centerY + Math.sin(angle) * distance,
initialSize * (0.7 + Math.random() * 0.3),
0
));
branches.push(nodes[i]);
}
// Grow fractal branches
nodes.forEach(node => node.grow());
}
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
branches.forEach(branch => branch.update());
branches.forEach(branch => branch.draw());
frames++;
requestAnimationFrame(animate);
}
init();
animate();
</script>
</body>
</html>