Skip to content

Instantly share code, notes, and snippets.

@gkucmierz
Created June 2, 2026 04:25
Show Gist options
  • Select an option

  • Save gkucmierz/82bdeb338e69dcce8b742f8a8dc3cb66 to your computer and use it in GitHub Desktop.

Select an option

Save gkucmierz/82bdeb338e69dcce8b742f8a8dc3cb66 to your computer and use it in GitHub Desktop.
Run this code instantly in your browser: https://instacode.app/gist/82bdeb338e69dcce8b742f8a8dc3cb66
// Mandelbrot Explorer for Instacode
// Features: Smooth zoom animation, continuous coloring, and HUD info display
import { canvas, getContext, onResize } from 'canvas';
const ctx = getContext('2d');
let width = 600;
let height = 400;
// Dynamic configuration
const maxIterations = 80;
let time = 0;
let currentX = -0.7;
let currentY = 0.0;
// Interesting deep point coordinates inside Mandelbrot set
const targetX = -0.7436438870371587;
const targetY = 0.13182590420531197;
// Automatically handle canvas resizing
onResize((w, h) => {
width = w;
height = h;
canvas.width = w;
canvas.height = h;
});
function draw() {
time += 0.005;
// Smoothly oscillate zoom in/out over time
// Using exponential zoom scaling
const zoomFactor = Math.pow(1.5, (Math.sin(time * 0.5) + 1.0) * 8.0) * 100;
// Linear interpolation to transition toward the target coordinates
const lerpT = 0.01;
currentX = currentX * (1.0 - lerpT) + targetX * lerpT;
currentY = currentY * (1.0 - lerpT) + targetY * lerpT;
const imgData = ctx.createImageData(width, height);
const data = imgData.data;
const halfW = width / 2;
const halfH = height / 2;
// Iterate over every pixel
for (let py = 0; py < height; py++) {
const y0 = (py - halfH) / zoomFactor + currentY;
const rowOffset = py * width * 4;
for (let px = 0; px < width; px++) {
const x0 = (px - halfW) / zoomFactor + currentX;
let x = 0.0;
let y = 0.0;
let iteration = 0;
// Cardioid and period-2 bulb optimization checks to skip rendering interior pixels
const q = (x0 - 0.25) * (x0 - 0.25) + y0 * y0;
if (q * (q + (x0 - 0.25)) < 0.25 * y0 * y0 || (x0 + 1.0) * (x0 + 1.0) + y0 * y0 < 0.0625) {
iteration = maxIterations;
} else {
// Standard escape time math
while (x * x + y * y <= 4.0 && iteration < maxIterations) {
const xtemp = x * x - y * y + x0;
y = 2.0 * x * y + y0;
x = xtemp;
iteration++;
}
}
const pixelIdx = rowOffset + px * 4;
if (iteration < maxIterations) {
// Continuous potential formula for beautiful, banding-free coloring
const log_zn = Math.log(x * x + y * y) / 2.0;
const nu = Math.log(log_zn / Math.log(2.0)) / Math.log(2.0);
const iterSmooth = iteration + 1.0 - nu;
// Dynamic color shifting based on elapsed time
const hue = (iterSmooth * 8 + time * 50) % 360;
const sat = 85;
const val = Math.min(100, iterSmooth * 3);
const rgb = hslToRgb(hue / 360, sat / 100, val / 100);
data[pixelIdx] = rgb[0];
data[pixelIdx + 1] = rgb[1];
data[pixelIdx + 2] = rgb[2];
data[pixelIdx + 3] = 255;
} else {
// Deep interior of the set (dark space)
data[pixelIdx] = 10;
data[pixelIdx + 1] = 15;
data[pixelIdx + 2] = 24;
data[pixelIdx + 3] = 255;
}
}
}
// Draw the fractal
ctx.putImageData(imgData, 0, 0);
// Draw a premium Sci-Fi HUD overlay
ctx.font = 'bold 12px monospace';
ctx.fillStyle = '#7ACED7';
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 4;
ctx.fillText('Mandelbrot Explorer v1.0', 20, 30);
ctx.fillStyle = '#8b949e';
ctx.fillText(`Center: ${currentX.toFixed(6)} + ${currentY.toFixed(6)}i`, 20, 50);
ctx.fillText(`Zoom: x${(zoomFactor / 100).toLocaleString(undefined, { maximumFractionDigits: 0 })}`, 20, 70);
ctx.fillText(`FPS: ~60 | Res: ${width}x${height}`, 20, 90);
ctx.shadowBlur = 0;
requestAnimationFrame(draw);
}
// Convert HSL values to RGB format
function hslToRgb(h, s, l) {
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const q = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
const p = 2.0 * l - q;
r = hueToRgb(p, q, h + 1.0 / 3.0);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1.0 / 3.0);
}
return [Math.round(r * 255.0), Math.round(g * 255.0), Math.round(b * 255.0)];
}
function hueToRgb(p, q, t) {
if (t < 0.0) t += 1.0;
if (t > 1.0) t -= 1.0;
if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;
if (t < 1.0 / 2.0) return q;
if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
return p;
}
// Initiate the animation loop
draw();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment