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="height" min=1 max=240 value=22></label>
<div class=value>22</div>
</div>
<div>
<label>Width: <input type="range" name="width" min=1 max=320 value=32></label>
<div class=value>32</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;
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,
time = 0;
function doLoop() {
for (let time = Date.now(); Date.now() - time < 50; ) {
if (py > maxY) {
py = 0;
px++;
}
if (px > maxX) {
// we're done!
console.log(vals, Date.now() - startTime);
if (ramp && maxIter < finalIter) {
maxIter++;
// give at least 100ms between loops
timeout = setTimeout(startLoop, 100 - (Date.now() - startTime));
}
return;
}
inner(px, py++);
}
console.log("took too long!");
// keep browser responsive - do more work on next timeout
timeout = setTimeout(doLoop, 10);
}
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;
maxX = document.getElementsByName('width')[0].value;
maxY = document.getElementsByName('height')[0].value;
scaleX = canvas.width / maxX;
scaleY = canvas.height / maxY;
scaleColor = 250 / maxIter;
console.log(scaleX, scaleY, scaleColor);
time = Date.now();
doLoop();
}
document.body.addEventListener('change', (event) => {
...