| title | ASCII Mandelbrot Set |
|---|---|
| route | /mandelbrot |
| date | 2020-05-05 |
| description |
This is rendering of the Mandelbrot set in ASCII, using HTML anchor tags and the address bar.
Click around to zoom in on different parts of the fractal, and use your browser history to zoom out.
You'll hit a wall pretty quickly due to the precision of numbers in JavaScript. Fraction.js gets us pretty close, though.
Feel free to poke around on GitHub if you have any ideas for improving this.
<style> #mandel { line-height: 1; white-space: nowrap; } @media (max-width: 480px) { #mandel { overflow-x: scroll; } } #mandel a:visited { color: green; } </style> <script src="/js/fraction.min.js"></script> <script> const WIDTH = 59; const HEIGHT = 30; const mandelChar = (a, b) => { let z_a = new Fraction(0); let z_b = new Fraction(0); let i = 0; while (i++ < 20) { /* z = z**2 + c */ // const _z_a = z_a*z_a - z_b * z_b + a; const _z_a = z_a.mul(z_a).sub(z_b.mul(z_b)).add(a); //const _z_b = 2 * z_a * z_b + b; const _z_b = z_a.mul(z_b).mul(2).add(b); z_a = _z_a; z_b = _z_b; //if (Math.sqrt(z_a * z_a + z_b * z_b) > 2) { if (z_a.mul(z_a).add(z_b.mul(z_b)).compare(4) > 0) { break; } } return ".:+x%#@"[Math.floor((i / 21) * 6)]; }; const draw = () => { const $el = document.getElementById("mandel") $el.innerHTML = ""; const [r, i, zoom] = document.location.hash .slice(1) .split(",") .map(i => new Fraction(i)); for (let j = 0; j < HEIGHT; j++) { // const y = (j / HEIGHT) * zoom + i - zoom / 2; const y = zoom.mul(j, HEIGHT).add(i).sub(zoom, 2); const row = document.createElement("div"); for (let k = 0; k < WIDTH; k++) { //const x = (k / WIDTH) * zoom + r - zoom / 2; const x = zoom.mul(k, WIDTH).add(r).sub(zoom, 2) const item = document.createElement("a"); const href = [x, y, zoom.mul(2, 3)].map(f => f.toFraction()).join(',') item.setAttribute("href", `#${href}`); item.innerHTML = mandelChar(x, y); row.appendChild(item); } $el.appendChild(row); } }; window.addEventListener("hashchange", draw); if (!/#[\d\-\/]+$/.test(document.location.hash)) { window.history.replaceState('', '', "#-1/2,0,7/2"); } draw(); </script>