fractal-lines-in-dark-space.../index.html

120 lines
No EOL
3.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 Attractor</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #000;
font-family: monospace;
color: #aaa;
display: flex;
justify-content: center;
align-items: flex-end;
}
canvas {
display: block;
}
#attribution {
position: fixed;
bottom: 10px;
left: 0;
right: 0;
text-align: center;
pointer-events: none;
font-size: 10px;
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 resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
// Strange attractor parameters (Rössler attractor)
let a = 0.2;
let b = 0.2;
let c = 5.7;
let d = 0.1;
let e = 0.1;
let scale = Math.min(canvas.width, canvas.height) * 0.3;
let x = 0.1;
let y = 0;
let z = 0;
let points = [];
const maxPoints = 10000;
const trailLength = 100;
// Motion parameter (0.5)
const motionFactor = 0.5;
const speed = 0.01 * motionFactor;
function draw() {
// Update attractor parameters with pulse influence (avg=1.08)
a = 0.2 + 0.05 * Math.sin(Date.now() * 0.001 * 1.08);
b = 0.2 + 0.05 * Math.cos(Date.now() * 0.001 * 1.05);
c = 5.7 + 0.5 * Math.sin(Date.now() * 0.001 * 1.10);
// Update attractor position
const dt = speed;
const x1 = x + dt * (-y - z);
const y1 = y + dt * (x + a * y);
const z1 = z + dt * (b + z * (x - c));
x = x1;
y = y1;
z = z1;
// Convert to 2D
const px = canvas.width/2 + x * scale;
const py = canvas.height/2 + y * scale;
// Add to points array
points.push({x: px, y: py});
if (points.length > maxPoints) {
points.shift();
}
// Draw
ctx.fillStyle = 'rgba(20, 20, 30, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = '#aaf';
ctx.lineWidth = 1.5;
ctx.beginPath();
for (let i = 1; i < points.length; i++) {
ctx.moveTo(points[i-1].x, points[i-1].y);
ctx.lineTo(points[i].x, points[i].y);
}
ctx.stroke();
// Draw some particles (density=0.5)
ctx.fillStyle = 'rgba(200, 220, 255, 0.3)';
for (let i = 0; i < points.length; i += 5) {
const size = 2 + Math.random() * 2;
ctx.beginPath();
ctx.arc(points[i].x, points[i].y, size, 0, Math.PI * 2);
ctx.fill();
}
requestAnimationFrame(draw);
}
draw();
</script>
</body>
</html>