<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Rotations</title>
<style>
html, body {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #222;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.10.0/p5.js"></script>
<!--
© Adam Murray 2025
https://adammurray.link/
Creative Commons License
Attribution-NonCommercial-ShareAlike 4.0 International
https://creativecommons.org/licenses/by-nc-sa/4.0/
-->
<script>
let MAX_DEPTH = 1;
let SIZE_DELTA = 1.04;
let ZOOM = 1 / 2.0;
let rot = 0;
let rotDelta = 0.02;
let autoAdvance = true;
function setup() {
const dim = Math.min(Math.min(1000, windowWidth), windowHeight) - 60;
createCanvas(dim, dim).parent("processing-canvas");
noFill();
strokeJoin(ROUND);
stroke(0, 255, 0, 60);
strokeWeight(130.0);
}
function draw() {
background(0);
scale(0.45);
translate(width * 0.8, height * 0.8);
subsqr(width, height, 1);
rot += rotDelta;
if (rot > 2 * PI) {
rot -= 2 * PI;
if (MAX_DEPTH < 3 && autoAdvance) {
MAX_DEPTH++;
}
}
}
function subsqr(w, h, depth) {
const xinc = ZOOM * w;
const yinc = ZOOM * h;
for (let x = 0; x < w; x += xinc) {
for (let y = 0; y < h; y += yinc) {
push();
translate(x, y);
rotate(rot);
scale(ZOOM);
if (depth < MAX_DEPTH) {
const pad = (1 - SIZE_DELTA) / 2.0;
translate(pad * w, pad * h);
subsqr(SIZE_DELTA * w, SIZE_DELTA * h, depth + 1);
} else {
rect(0, 0, w, h);
}
pop();
}
}
}
function keyPressed() {
if (key >= "1" && key <= "7") {
MAX_DEPTH = key - "0";
autoAdvance = false;
}
}
</script>
</head>
<body>
<div id="processing-canvas"></div>
</body>
</html>