birth: Drifting Strange Attractor's Whisper
This commit is contained in:
parent
17bae5a552
commit
00530e0771
1 changed files with 148 additions and 0 deletions
148
index.html
Normal file
148
index.html
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Drifting Strange Attractor</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #0a0a0a;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#info {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 20px;
|
||||||
|
font-size: 10px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="canvas"></canvas>
|
||||||
|
<div id="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();
|
||||||
|
|
||||||
|
// Strange attractor parameters based on input
|
||||||
|
const params = {
|
||||||
|
a: 0.524 * 2.5 - 1.0,
|
||||||
|
b: 0.454 * 2.5,
|
||||||
|
c: 0.520 * 3.0 + 1.0,
|
||||||
|
d: 0.488 * 2.5 - 1.0,
|
||||||
|
motion: 0.58,
|
||||||
|
density: 0.454,
|
||||||
|
trailLength: 25 + Math.floor(0.454 * 30),
|
||||||
|
maxDepth: 15,
|
||||||
|
pulse: 0.58
|
||||||
|
};
|
||||||
|
|
||||||
|
// Color palette based on tone
|
||||||
|
const colors = {
|
||||||
|
curiosity: '#40e0d0', // teal
|
||||||
|
dryness: '#e0e0e0', // monochrome
|
||||||
|
playfulness: '#ff8888' // slightly vibrant
|
||||||
|
};
|
||||||
|
|
||||||
|
// Point system
|
||||||
|
class Point {
|
||||||
|
constructor(x, y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.history = [];
|
||||||
|
this.maxLength = params.trailLength;
|
||||||
|
this.pulse = params.pulse * (0.7 + Math.random() * 0.6);
|
||||||
|
this.depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(ax, ay, bx, by, cx, cy, dx, dy) {
|
||||||
|
const xn = Math.sin(ax * this.y) - Math.cos(bx * this.x);
|
||||||
|
const yn = Math.sin(cy * this.x) - Math.cos(dx * this.y);
|
||||||
|
|
||||||
|
this.x += xn * 0.01 * this.pulse;
|
||||||
|
this.y += yn * 0.01 * this.pulse;
|
||||||
|
|
||||||
|
// Add to history
|
||||||
|
this.history.push({x: this.x, y: this.y});
|
||||||
|
if (this.history.length > this.maxLength) {
|
||||||
|
this.history.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.depth = Math.min(this.depth + 0.01, params.maxDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
ctx.beginPath();
|
||||||
|
|
||||||
|
// Draw trail
|
||||||
|
for (let i = 0; i < this.history.length; i++) {
|
||||||
|
const p = this.history[i];
|
||||||
|
const alpha = i / this.history.length;
|
||||||
|
const size = 1 + (this.maxLength - i) / this.maxLength * 0.8;
|
||||||
|
|
||||||
|
ctx.globalAlpha = alpha * 0.7;
|
||||||
|
ctx.fillStyle = colors.dryness;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(p.x * canvas.width, p.y * canvas.height, size, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.globalAlpha = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create points based on density
|
||||||
|
const points = [];
|
||||||
|
const count = 50 + Math.floor(params.density * 150);
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
points.push(new Point(
|
||||||
|
Math.random(),
|
||||||
|
Math.random()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation loop
|
||||||
|
let frame = 0;
|
||||||
|
function animate() {
|
||||||
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Update and draw points
|
||||||
|
for (const p of points) {
|
||||||
|
p.update(
|
||||||
|
params.a + Math.sin(frame * 0.01) * 0.1,
|
||||||
|
params.b,
|
||||||
|
params.c,
|
||||||
|
params.d + Math.cos(frame * 0.02) * 0.05,
|
||||||
|
params.a,
|
||||||
|
params.b * 0.5,
|
||||||
|
params.c,
|
||||||
|
params.d * 1.2
|
||||||
|
);
|
||||||
|
p.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
frame++;
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
animate();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue