whispering-circuit-gardens-.../index.html

209 lines
No EOL
6.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neurameba Motd</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #0a0a1a;
color: #ffffff;
font-family: 'Courier New', monospace;
}
canvas {
display: block;
}
#attribution {
position: fixed;
bottom: 10px;
right: 10px;
font-size: 10px;
color: #555;
pointer-events: none;
}
</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
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
},
tone: {
curiosity: 0.7,
dryness: 0.9,
playfulness: 0.1
}
};
// Node and edge properties
const nodes = [];
const edges = [];
const maxNodes = 150;
const maxEdges = 300;
const nodeRadius = () => 2 + Math.random() * 3;
const edgeWidth = () => 0.5 + Math.random() * 1.5;
// Color palette
const palette = {
background: '#0a0a1a',
node: '#4a7c59',
edge: '#2a5c39',
highlight: '#6a9c79'
};
// Pulse simulation
let pulseTime = 0;
let pulseDirection = 1;
// Initialize nodes
for (let i = 0; i < maxNodes; i++) {
nodes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: nodeRadius(),
velocity: {
x: (Math.random() - 0.5) * 2 * params.motion,
y: (Math.random() - 0.5) * 2 * params.motion
},
lifespan: params.lifespan * (0.5 + Math.random() * 0.5),
age: 0
});
}
// Initialize edges
for (let i = 0; i < maxEdges; i++) {
const a = Math.floor(Math.random() * nodes.length);
const b = Math.floor(Math.random() * nodes.length);
if (a !== b) {
edges.push({
from: a,
to: b,
thickness: edgeWidth(),
age: 0,
maxAge: params.lifespan * (0.3 + Math.random() * 0.7)
});
}
}
// Simulation
function update() {
// Update pulse
pulseTime += 0.01 * pulseDirection;
if (pulseTime > params.pulse.max || pulseTime < params.pulse.min) {
pulseDirection *= -1;
}
// Update nodes
nodes.forEach(node => {
// Bounce off edges
if (node.x < 0 || node.x > canvas.width) node.velocity.x *= -1;
if (node.y < 0 || node.y > canvas.height) node.velocity.y *= -1;
// Update position
node.x += node.velocity.x;
node.y += node.velocity.y;
// Age node
node.age += 0.01;
if (node.age > node.lifespan) {
// Respawn if lifespan is short
node.x = Math.random() * canvas.width;
node.y = Math.random() * canvas.height;
node.age = 0;
}
});
// Update edges
edges.forEach(edge => {
edge.age += 0.01;
if (edge.age > edge.maxAge) {
// Remove old edges
const index = edges.indexOf(edge);
if (index > -1) edges.splice(index, 1);
}
});
// Add new edges based on connectedness
if (Math.random() < params.connectedness * 0.02) {
const a = Math.floor(Math.random() * nodes.length);
const b = Math.floor(Math.random() * nodes.length);
if (a !== b) {
edges.push({
from: a,
to: b,
thickness: edgeWidth(),
age: 0,
maxAge: params.lifespan * (0.3 + Math.random() * 0.7)
});
}
}
}
// Drawing
function draw() {
// Clear with slight blur for motion trails
ctx.fillStyle = palette.background;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw edges
ctx.strokeStyle = palette.edge;
ctx.lineWidth = 0.5 * pulseTime;
edges.forEach(edge => {
const a = nodes[edge.from];
const b = nodes[edge.to];
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
ctx.stroke();
});
// Draw nodes
ctx.fillStyle = palette.node;
nodes.forEach(node => {
ctx.beginPath();
ctx.arc(node.x, node.y, node.radius * pulseTime, 0, Math.PI * 2);
ctx.fill();
// Highlight based on age
const highlight = Math.min(1, node.age / node.lifespan);
ctx.strokeStyle = `rgba(106, 156, 121, ${highlight * 0.3})`;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(node.x, node.y, node.radius * pulseTime * 1.5, 0, Math.PI * 2);
ctx.stroke();
});
}
// Animation loop
function animate() {
update();
draw();
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>