JSFiddle - React, Tailwind, and code Playground
by fxi
HTML
<input id="slider" type="number" step="1" min="0" max="255" value="30">
<canvas id="canvas"></canvas>
CSS
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
JavaScript
const elSlider = document.getElementById('slider');
elSlider.addEventListener('input', (e) => {
config.ruleNumber = e.target.value * 1;
update();
})
// Configuration
const config = {
cellResolution: 5, // Size of each cell in pixels
ruleNumber: 73 // Rule number for the automaton
};
elSlider.value = config.ruleNumber ;
// Initialization
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
function update() {
// Convert the rule number to binary
config.ruleBinary = config.ruleNumber.toString(2).padStart(8, '0').split('').map(Number);
// Starting state with a single '1' in the middle
config.rowWidth = Math.floor(canvas.width / config.cellResolution);
let currentState = Array(config.rowWidth).fill(0);
currentState[Math.floor(config.rowWidth / 2)] = 1;
draw(currentState);
}
// Compute next state based on the rule
function computeNextState(current) {
let newState = [];
for (let i = 0; i < current.length; i++) {
let left = current[i - 1] || 0;
let center = current[i];
let right = current[i + 1] || 0;
let ruleIndex = 7 - (left * 4 + center * 2 + right);
newState[i] = config.ruleBinary[ruleIndex];
}
return newState;
}
// Draw function
function draw(currentState) {
for (let y = 0; y < canvas.height; y += config.cellResolution) {
for (let x = 0; x < config.rowWidth * config.cellResolution; x += config.cellResolution) {
let cellState = currentState[Math.floor(x / config.cellResolution)];
ctx.fillStyle = cellState === 1 ? 'black' : 'white';
ctx.fillRect(x, y, config.cellResolution, config.cellResolution);
}
currentState = computeNextState(currentState);
}
}
update()