Mandlebrot

by nynexman4464

HTML

<canvas width=320 height=240>How old is your browser?</canvas>
<div id=controls>
  <div>
    <label>Height: <input type="range" name="width" min=1 max=320 value=32></label>
    <div class=value>32</div>
  </div>
  <div>
    <label>Width: <input type="range" name="height" min=1 max=240 value=22></label>
    <div class=value>22</div>
  </div>
  <div><label>Iter: <input type="range" name="iterations" min=1 max=1000 value=14></label>
    <div class=value>14</div>
  </div>
  <button onClick="start()">
    go
  </button>
</div>

CSS

body {
  display: flex;
  direction: row;
}

#controls {
  margin-left: 1em;
}

#controls div {
  display: grid;
  grid-template-columns: auto;
}
label{display: grid}

@media (prefers-color-scheme: dark) {
  body {
    background: black;
    color: white;
  }
}

JavaScript

const meta = document.createElement('meta');
meta.name = "color-scheme";
meta.content = "light dark";
document.head.appendChild(meta);
const canvas = document.getElementsByTagName('canvas')[0];
const context = canvas.getContext('2d');
let maxY = 64;
let maxX = 48;
let maxIter = 100;

function inner(px, py) {
  let xz = px * 3.5 / maxX - 2.5;
  let yz = py * 2 / maxY - 1;
  console.log({px,py,xz,yz});
  let x = 0;
  let y = 0;
  let i = 0;
  for (i = 0; i <= maxIter; i++) {
    if (x * x + y * y > 4) {
      break;
    }
    let xt = x * x - y * y + xz;
    y = 2 * x * y + yz;
    x = xt;
  }
  let color = i - 1;
  requestAnimationFrame(() => plot(color, px, py));
}

let px = 0,
  py = 0;

function doLoop() {
  if (py > maxY) {
    py = 0;
    px++;
  }
  if (px > maxX) {
    console.log(vals);
    return;
  }
  inner(px, py++);
  setTimeout(doLoop, 0);
}

const vals = [];

let scaleX, scaleY, scaleColor;

function plot(color, x, y) {
  vals[x] ? (vals[x][y] = color) : (vals[x] = [color]);
  context.fillStyle = `hsl(${color*(scaleColor)},100%,50%)`;
  context.fillRect(x * scaleX, y * scaleY, scaleX, scaleY);
  //console.log(color, x, y);
}

function start() {

  px = 0;
  py = 0;
  maxIter = document.getElementsByName('iterations')[0].value;
  maxWidth = document.getElementsByName('width')[0].value;
  maxHeight = document.getElementsByName('height')[0].value;

  scaleX = canvas.width / maxX;
  scaleY = canvas.height / maxY;
  scaleColor = 250 / maxIter;
  console.log(scaleX, scaleY, scaleColor);
  doLoop();
}
document.body.addEventListener('change', (event) => {
  if (event.target.tagName == 'INPUT') {
    event.target.parentNode.parentNode.querySelector('.value').innerText = event.target.value;
  }
})
start();