diffusive-echoes-in-monochr.../index.html

180 lines
No EOL
5.9 KiB
HTML

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Diffusive Echoes</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #0a0a0a;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: 'Courier New', monospace;
}
canvas {
display: block;
}
#attribution {
position: absolute;
bottom: 20px;
color: rgba(255, 255, 255, 0.3);
font-size: 10px;
}
</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');
// Set canvas to full window size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// Reaction-diffusion parameters (adjusted for aesthetic)
const params = {
feed: 0.055,
kill: 0.062,
diffA: 1.0,
diffB: 0.5,
timeStep: 1.0,
colorShiftSpeed: 0.001,
densityScale: 0.6
};
// Use complexity to vary parameters
params.diffA = 0.8 + (0.5 * 0.5); // Between 0.8 and 1.05
params.diffB = 0.4 + (0.5 * 0.2); // Between 0.4 and 0.5
// Initialize grids
const size = Math.floor(100 * params.densityScale);
const gridWidth = Math.floor(canvas.width / size) + 2;
const gridHeight = Math.floor(canvas.height / size) + 2;
const grid = new Array(gridWidth * gridHeight);
const nextGrid = new Array(gridWidth * gridHeight);
// Fill initial grid with random values
for (let i = 0; i < grid.length; i++) {
grid[i] = Math.random() > 0.5 ? 1 : 0;
nextGrid[i] = 0;
}
// Color palette (dryness = monochrome with slight variation)
let hue = 0;
function getColor(value) {
hue = (hue + params.colorShiftSpeed) % 1;
const intensity = Math.pow(value, 0.5);
return `hsl(${hue * 60}, ${10 + value * 90}%, ${20 + intensity * 30}%)`;
}
// Reaction-diffusion step
function updateGrid() {
const width = gridWidth;
const height = gridHeight;
for (let x = 1; x < width - 1; x++) {
for (let y = 1; y < height - 1; y++) {
const index = x + y * width;
const currentA = grid[index];
const currentB = 1 - currentA;
// Calculate neighborhood sum
let sumA = 0;
let sumB = 0;
for (let dx = -1; dx <= 1; dx++) {
for (let dy = -1; dy <= 1; dy++) {
if (dx === 0 && dy === 0) continue;
const neighborIndex = (x + dx) + (y + dy) * width;
sumA += grid[neighborIndex];
sumB += 1 - grid[neighborIndex];
}
}
const neighbors = 8;
sumA /= neighbors;
sumB /= neighbors;
// Reaction-diffusion equations
const newA = currentA + (
params.diffA * sumA -
currentA * currentB * currentB +
params.feed * (1 - currentA)
) * params.timeStep;
const newB = currentB + (
params.diffB * sumB +
currentA * currentB * currentB -
(params.kill + params.feed) * currentB
) * params.timeStep;
nextGrid[index] = Math.min(Math.max(newA, 0), 1);
}
}
// Swap grids
const temp = grid;
grid.length = 0;
nextGrid.forEach(val => grid.push(val));
nextGrid.length = 0;
for (let i = 0; i < grid.length; i++) {
nextGrid[i] = 0;
}
}
// Drawing function
function draw() {
ctx.globalAlpha = 0.9;
ctx.fillStyle = 'rgba(10, 10, 10, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const size = Math.floor(100 * params.densityScale);
const width = gridWidth;
const height = gridHeight;
for (let x = 1; x < width - 1; x++) {
for (let y = 1; y < height - 1; y++) {
const index = x + y * width;
const value = grid[index];
if (value > 0.5) {
const px = (x - 1) * size;
const py = (y - 1) * size;
ctx.fillStyle = getColor(value);
ctx.beginPath();
ctx.arc(px + size/2, py + size/2, size/2 * (0.3 + 0.7 * value), 0, Math.PI * 2);
ctx.fill();
}
}
}
}
// Animation loop
let lastTime = 0;
function animate(currentTime) {
const deltaTime = (currentTime - lastTime) / 1000;
lastTime = currentTime;
// Adjust parameters based on motion
params.feed = 0.055 + Math.sin(currentTime * 0.001) * 0.01;
params.kill = 0.062 + Math.cos(currentTime * 0.0015) * 0.01;
updateGrid();
draw();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
</script>
</body>
</html>
```