birth: Fractal Tendrils in Pulsing Stillness

This commit is contained in:
motd_admin 2026-03-27 09:47:14 +00:00
parent cd81545635
commit 6c316ab240

151
index.html Normal file
View file

@ -0,0 +1,151 @@
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Organic Fractal Bloom</title>
<style>
body { margin: 0; overflow: hidden; background: #0a0a0a; }
canvas { display: block; }
#attribution { position: fixed; bottom: 10px; right: 10px; color: #555; font-family: monospace; font-size: 10px; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div id="attribution">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();
// L-system parameters derived from the abstract specs
const params = {
axiom: 'X',
rules: {
'X': 'F-[[X]+X]+F[+FX]-X',
'F': 'FF'
},
angle: 25,
iterations: 4,
stepLength: 20,
stepReduction: 0.92,
randomness: 0.2,
colorBase: [220, 220, 220],
saturation: 0.1,
brightness: 0.5,
pulsationSpeed: 0.5
};
let angle = 0;
let pulsation = 0.72;
function drawLSys() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
// Apply pulsation effect
pissation = 0.72 + Math.sin(Date.now() * 0.001 * params.pulsationSpeed) * 0.5;
ctx.translate(canvas.width / 2, canvas.height / 1.5);
// Draw recursive branches
const turns = ['F', '+', '-', '[', ']'];
let stack = [];
let hueVariation = 0;
let branchCount = 0;
function drawSegment(length, depth) {
branchCount++;
if (branchCount > 11) return; // Branch count constraint
// Color variation based on dryness
const hue = (20 + hueVariation * 10) % 360;
const saturation = params.saturation * 100;
const brightness = params.brightness * (0.5 + pulsation * 0.5);
ctx.strokeStyle = `hsl(${hue}, ${saturation}%, ${brightness}%)`;
ctx.lineWidth = Math.max(0.5, length * 0.05 * (1 + pulsation * 0.5));
// Add some organic roughness
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.beginPath();
ctx.moveTo(0, 0);
const x = length * Math.cos(angle);
const y = length * Math.sin(angle);
ctx.lineTo(x, y);
ctx.stroke();
// Branch recursion
if (depth > 0) {
ctx.save();
ctx.translate(x, y);
angle += Math.random() * params.randomness - params.randomness * 0.5;
drawSegment(length * params.stepReduction, depth - 1);
ctx.restore();
}
}
// Generate path with loops
let currentString = params.axiom;
for (let i = 0; i < params.iterations; i++) {
let nextString = '';
for (let c of currentString) {
if (params.rules[c]) {
nextString += params.rules[c];
} else {
nextString += c;
}
}
currentString = nextString;
}
// Draw the L-system with some randomness
ctx.save();
for (let i = 0; i < currentString.length; i++) {
const c = currentString[i];
if (c === 'F') {
drawSegment(params.stepLength, 5);
angle += Math.random() * params.randomness;
} else if (c === '+') {
angle += params.angle * (1 + Math.random() * params.randomness);
} else if (c === '-') {
angle -= params.angle * (1 + Math.random() * params.randomness);
} else if (c === '[') {
stack.push({x: ctx.lineTo(), y: ctx.lineTo(), angle: angle});
} else if (c === ']') {
const point = stack.pop();
if (point) {
ctx.lineTo(point.x, point.y);
angle = point.angle;
}
} else if (c === 'X') {
// Skip drawing X elements directly
}
// Adjust color slightly for each segment
hueVariation += 0.1;
}
ctx.restore();
ctx.restore();
}
function animate() {
angle += 0.01;
drawLSys();
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>
```