strange-entropy-pulse-1j6q/index.html

191 lines
No EOL
6.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>strange entropy</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #0a0a0a;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
canvas {
display: block;
}
.info {
position: absolute;
bottom: 20px;
color: #555;
font-family: 'Courier New', monospace;
font-size: 11px;
pointer-events: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="info">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 specs
const params = {
motion: 0.421,
density: 0.577,
complexity: 0.380,
connectedness: 0.556,
lifespan: 0.636,
pulseAvg: 0.34,
pulseMin: 0.30,
pulseMax: 1.30,
dryness: 0.90
};
// Strange attractor parameters (Lorenz-like)
let attractor = {
a: 10,
b: 28,
c: 8/3,
x: 0.1,
y: 0.1,
z: 0.1,
history: [],
maxHistory: 200,
trailLength: Math.floor(params.lifespan * 100) + 50,
pointSize: (params.density * 0.8) + 0.5,
color: params.dryness > 0.7 ? '#ddd' : '#0ff'
};
// Initialize network connections
const nodes = [];
const branches = Math.floor(params.connectedness * 100) + 5;
const nodeCount = Math.floor(params.density * 50) + 10;
for (let i = 0; i < nodeCount; i++) {
nodes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: 0,
vy: 0,
size: attractor.pointSize * (0.5 + Math.random() * 0.5),
connections: [],
maxConnections: Math.floor(params.connectedness * 5) + 1,
age: 0
});
}
// Create connections (branches)
for (let i = 0; i < branches; i++) {
const from = Math.floor(Math.random() * nodeCount);
const to = Math.floor(Math.random() * nodeCount);
if (from !== to && nodes[from].connections.length < nodes[from].maxConnections) {
nodes[from].connections.push(nodes[to]);
}
}
// Animation state
let time = 0;
let lastPulse = 0;
function animate() {
// Calculate pulse effect from parameters
const pulsePhase = params.pulseAvg + Math.sin(time * 0.01) * 0.2;
const pulse = params.pulseMin + (params.pulseMax - params.pulseMin) * pulsePhase;
attractor.pointSize = (params.density * 0.8 + 0.5) * (0.8 + pulse * 0.2);
// Clear with semi-transparent to create trails
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Update attractor
for (let i = 0; i < 5; i++) {
const dt = 0.01 * (params.motion * 2 + 0.1);
attractor.x += dt * (attractor.a * (attractor.y - attractor.x));
attractor.y += dt * (attractor.x * (attractor.b - attractor.z) - attractor.y);
attractor.z += dt * (attractor.x * attractor.y - attractor.c * attractor.z);
// Store position with slight variation
attractor.history.push({
x: attractor.x * 20 + canvas.width/2,
y: attractor.y * 20 + canvas.height/2,
size: attractor.pointSize * (1 + attractor.z * 0.05)
});
if (attractor.history.length > attractor.maxHistory) {
attractor.history.shift();
}
}
// Draw attractor trail
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
if (attractor.history.length > 1) {
ctx.beginPath();
ctx.moveTo(attractor.history[0].x, attractor.history[0].y);
for (let i = 1; i < attractor.history.length; i++) {
ctx.lineTo(attractor.history[i].x, attractor.history[i].y);
}
ctx.stroke();
}
// Update and draw nodes
nodes.forEach(node => {
// Simple movement
node.vx += (Math.random() - 0.5) * 0.2 * params.motion;
node.vy += (Math.random() - 0.5) * 0.2 * params.motion;
node.vx *= 0.9;
node.vy *= 0.9;
node.x += node.vx;
node.y += node.vy;
node.x = (node.x + canvas.width) % canvas.width;
node.y = (node.y + canvas.height) % canvas.height;
node.age++;
// Draw node
ctx.beginPath();
ctx.arc(node.x, node.y, node.size, 0, Math.PI * 2);
ctx.fillStyle = params.dryness > 0.7 ? '#aaa' : '#0ff';
ctx.fill();
// Draw connections
node.connections.forEach(conn => {
ctx.beginPath();
ctx.moveTo(node.x, node.y);
ctx.lineTo(conn.x, conn.y);
ctx.strokeStyle = `rgba(170, 255, 255, ${Math.min(0.3, node.age/100)})`;
ctx.lineWidth = params.connectedness * 0.8 + 0.3;
ctx.stroke();
});
});
// Occasionally reset some nodes
if (Math.random() < 0.01 * params.motion) {
const idx = Math.floor(Math.random() * nodeCount);
nodes[idx].x = Math.random() * canvas.width;
nodes[idx].y = Math.random() * canvas.height;
}
time++;
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>