birth: Fractal Fronds in Darkness
This commit is contained in:
parent
ab8bc7eca7
commit
4bbf5c5faa
1 changed files with 184 additions and 0 deletions
184
index.html
Normal file
184
index.html
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Neurameba · motd.social</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
font-family: monospace;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#attribution {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</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();
|
||||||
|
|
||||||
|
// Parameters derived from abstract inputs
|
||||||
|
const params = {
|
||||||
|
motion: 0.5,
|
||||||
|
density: 0.5,
|
||||||
|
complexity: 0.5,
|
||||||
|
connectedness: 0.5,
|
||||||
|
lifespan: 0.5,
|
||||||
|
pulse: { avg: 1.1, min: 1.0, max: 1.2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// L-system rules with dynamic adaptation
|
||||||
|
const lSystem = {
|
||||||
|
axiom: 'A',
|
||||||
|
rules: {
|
||||||
|
'A': 'B[+A][-A]AB',
|
||||||
|
'B': 'A[-B][+B]BA'
|
||||||
|
},
|
||||||
|
angle: Math.PI * 0.3,
|
||||||
|
length: 120,
|
||||||
|
depth: 6,
|
||||||
|
strokeWidth: 1.5,
|
||||||
|
hue: 0,
|
||||||
|
saturation: 0,
|
||||||
|
brightness: 100,
|
||||||
|
opacity: 0.8
|
||||||
|
};
|
||||||
|
|
||||||
|
// Animation state
|
||||||
|
let time = 0;
|
||||||
|
const branches = [];
|
||||||
|
|
||||||
|
// Initialize L-system
|
||||||
|
function initSystem() {
|
||||||
|
const stack = [];
|
||||||
|
let current = lSystem.axiom;
|
||||||
|
const lengthFactor = 0.6;
|
||||||
|
const angleFactor = 1.0;
|
||||||
|
let depth = 0;
|
||||||
|
|
||||||
|
// Calculate depth based on complexity
|
||||||
|
lSystem.depth = Math.floor(4 + params.complexity * 4);
|
||||||
|
|
||||||
|
// Process the string
|
||||||
|
for (let i = 0; i < current.length; i++) {
|
||||||
|
const c = current[i];
|
||||||
|
|
||||||
|
if (c === '[') {
|
||||||
|
stack.push({ pos: [...getCurrentPos()], angle: getCurrentAngle(), length: lSystem.length });
|
||||||
|
} else if (c === ']') {
|
||||||
|
const state = stack.pop();
|
||||||
|
setCurrentPos(state.pos);
|
||||||
|
setCurrentAngle(state.angle);
|
||||||
|
lSystem.length = state.length;
|
||||||
|
} else if (c === '+') {
|
||||||
|
setCurrentAngle(getCurrentAngle() + lSystem.angle * angleFactor * (0.7 + params.motion * 0.3));
|
||||||
|
} else if (c === '-') {
|
||||||
|
setCurrentAngle(getCurrentAngle() - lSystem.angle * angleFactor * (0.7 + params.motion * 0.3));
|
||||||
|
} else if (c === 'A' || c === 'B') {
|
||||||
|
const newLength = lSystem.length * lengthFactor;
|
||||||
|
const startPos = [...getCurrentPos()];
|
||||||
|
const endPos = [
|
||||||
|
getCurrentPos()[0] + newLength * Math.cos(getCurrentAngle()),
|
||||||
|
getCurrentPos()[1] + newLength * Math.sin(getCurrentAngle())
|
||||||
|
];
|
||||||
|
const hue = (lSystem.hue + Math.random() * 30) % 360;
|
||||||
|
|
||||||
|
branches.push({
|
||||||
|
start: startPos,
|
||||||
|
end: endPos,
|
||||||
|
length: newLength,
|
||||||
|
hue: hue,
|
||||||
|
saturation: lSystem.saturation,
|
||||||
|
brightness: lSystem.brightness,
|
||||||
|
opacity: lSystem.opacity * (0.5 + params.lifespan * 0.5),
|
||||||
|
time: time
|
||||||
|
});
|
||||||
|
|
||||||
|
setCurrentPos(endPos);
|
||||||
|
lSystem.length = newLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position and angle tracking
|
||||||
|
let currentPos = [canvas.width/2, canvas.height/2];
|
||||||
|
let currentAngle = 0;
|
||||||
|
|
||||||
|
function getCurrentPos() { return [...currentPos]; }
|
||||||
|
function getCurrentAngle() { return currentAngle; }
|
||||||
|
function setCurrentPos(pos) { currentPos = [...pos]; }
|
||||||
|
function setCurrentAngle(angle) { currentAngle = angle; }
|
||||||
|
|
||||||
|
// Draw branches with pulsing effect
|
||||||
|
function drawBranches() {
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const pulseFactor = params.pulse.avg + Math.sin(time * 0.002) * 0.1 * (params.pulse.max - params.pulse.min);
|
||||||
|
const maxBranches = Math.floor(50 + params.density * 150);
|
||||||
|
|
||||||
|
// Filter and draw branches
|
||||||
|
branches.forEach(branch => {
|
||||||
|
if (branch.opacity > 0.01) {
|
||||||
|
const age = time - branch.time;
|
||||||
|
const opacity = branch.opacity * (1 - age * 0.0001);
|
||||||
|
|
||||||
|
if (opacity > 0.01) {
|
||||||
|
ctx.strokeStyle = `hsla(${branch.hue}, ${branch.saturation}%, ${branch.brightness}%, ${opacity})`;
|
||||||
|
ctx.lineWidth = branch.length * 0.05 * pulseFactor * (0.8 + params.motion * 0.2);
|
||||||
|
ctx.lineCap = 'round';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(...branch.start);
|
||||||
|
ctx.lineTo(...branch.end);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prune old branches based on lifespan
|
||||||
|
if (params.lifespan < 0.3) {
|
||||||
|
branches.forEach((branch, i) => {
|
||||||
|
if (time - branch.time > 1000) {
|
||||||
|
branch.opacity *= 0.9;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function animate() {
|
||||||
|
time++;
|
||||||
|
drawBranches();
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
initSystem();
|
||||||
|
animate();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue