const pre = document.getElementById("main"); // the cool spinning circles on index.html const rnd = (n) => Math.floor(Math.random() * n); const points = []; let time = 0; let charRows, charCols, charHeight; // handle page resizes without ruining everything function resize() { const canvas = new OffscreenCanvas(100, 100); const context = canvas.getContext("2d"); context.font = getComputedStyle(pre).font; const measured = context.measureText("x"); charHeight = measured.fontBoundingBoxAscent + 5; charRows = Math.floor((window.innerHeight) / charHeight); charCols = Math.floor((window.innerWidth - 5) / measured.width); } const shades = " .:=+*#%".split(""); // const shades = "01234567".split(""); const shaders = [ // stripes (t, x, y) => { return shades[Math.floor(Math.abs((x * t / 30) + (y * t / 15)) * t / 10) % 8] }, // circles (t, x, y) => { return shades[Math.floor(Math.sqrt(x ** 2 + y ** 2) * (t / 10)) % 8] }, // mandelbrot (t, x, y) => { const scale = 20000 / (t + 100) ** 2; let x0 = x * scale - .803, y0 = y * scale - .167, x1 = 0, y1 = 0, i = 0; for (; i < 100 && x1 ** 2 + y1 ** 2 <= 2 ** 2; i++) { const tmp = x1 ** 2 - y1 ** 2 + x0; y1 = 2 * x1 * y1 + y0; x1 = tmp; } return shades[Math.floor(i) % 8]; }, (t, x, y) => { const xs = x * t / 3; const ys = y * t / 3; return shades[Math.floor(Math.abs((xs % ys || 0) - (ys % xs || 0))) % 8] }, (t, x, y) => { const s = ((x / y + t / 10) & 1 / y & 1) && y > 0; return shades[Math.floor(s) % 8] }, (t, x, y) => { return shades[(Math.cos(50*Math.sin((y)/(x))+5*(t/30))+1)*4<<0]; }, // FIXME: broken on some screen resolutions // (t, x, y) => { // const rows = [ // " __ ", // " ________ / /__ _______ __ ___ __ __ ____ _________ _", // " / ___/ _ \\/ / _ \\/ ___/ / / // _ \\/ / / // __ \\/ ___/ __ `/", // "/ /__/ __/ / __/ / / /_/ // __/ /_/ // /_/ / / / /_/ / ", // "\\___/\\___/_/\\___/_/ \\__, (_)___/\\__,_(_)____/_/ \\__, / ", // " /____/ /____/ ", // ]; // const tween = Math.sin(t / 30 + x * 2) * 3; // const ch = rows[Math.round(tween + y * (charRows / 2)) + (rows.length / 2)]?.[Math.round(x * (charCols / 2)) + rows[0].length / 2]; // return ch || " "; // }, ]; // const shader = shaders[Math.random() * shaders.length << 0]; const shader = shaders[2]; function shade(x, y) { return shader( time, (x / (charCols / 2)) - 1, (y / (charRows / 2)) - 1, ); } const rows = []; function draw() { if (rows.length !== charRows) { while (rows.length) rows.pop().remove(); for (let i = 0; i < charRows; i++) { const el = document.createElementNS("http://www.w3.org/2000/svg", "text"); el.setAttribute("x", 5); el.setAttribute("y", i * charHeight + charHeight); el.setAttribute("fill", "grey"); el.style.fontSize = "16px"; el.style.whiteSpace = "pre"; el.textContent = "you are at celery.eu.org"; rows.push(el); pre.append(el); } } for (let y = 0; y < charRows; y++) { let buf = ""; for (let x = 0; x < charCols; x++) { buf += shade(x, y); } rows[y].textContent = buf; } requestAnimationFrame(draw); } function init() { resize(); window.addEventListener("resize", resize); for (let i = 0; i < 10; i++) { points.push({ shade: "celry"[Math.floor(Math.random() * 5)], radius: Math.random() * 600 + 300, speed: Math.random() / 10 + 0.1, rot: Math.random() * 2 * Math.PI, }); } draw(); } init(); setInterval(() => time++, 1000 / 60);