Mandelbrot explorer · gemini-3.1-flash-lite
Render the Mandelbrot set with a smooth color gradient on a full-screen canvas, with click-and-drag to pan and mouse-wheel to zoom.
transcript · 4 messages
Render the Mandelbrot set with a smooth color gradient on a full-screen canvas, with click-and-drag to pan and mouse-wheel to zoom.
thinking
**Developing the Mandelbrot App** I'm making good progress on the single-page web app. The basic HTML structure and full-screen canvas are set. Next, I'm focusing on implementing a smooth color gradient to make the fractal visually appealing. Once I get the colors right, I'll integrate click-and-drag panning and mouse-wheel zoom for interactivity. **Defining the Coordinate System** I've got the basic HTML structure set, and the canvas is ready to go. I'm deep diving into defining the coordinate system, mapping pixel coordinates to the complex plane. I am getting the `draw()` function ready, to translate the user input into visible output, handling the `zoom` and `center` variables for interactive manipulation. The next step is fleshing out the pixel mapping logic.
index.html (4205 bytes)Successfully wrote 4205 bytes to index.html
The Mandelbrot set renderer has been created as `index.html`. You can open this file in any web browser to interact with it. ### Features * **Smooth Coloring:** Uses a fractional iteration count to create a continuous gradient rather than stepped bands. * **Controls:** * **Click & Drag:** Pan across the fractal coordinate space. * **Mouse Wheel:** Zoom in and out. * **Adaptive Performance:** Automatically increases the calculation depth (`maxIter`) as you zoom deeper to maintain detail. ```html <!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mandelbrot Explorer</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; background: #000; } canvas { display: block; cursor: crosshair; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); let width, height; let centerX = -0.5, centerY = 0; let zoom = 200; let maxIter = 100; function resize() { width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; draw(); } window.addEventListener('resize', resize); resize(); function mandelbrot(cx, cy) { let x = 0, y = 0; let iter = 0; while (x * x + y * y <= 4 && iter < maxIter) { let xTemp = x * x - y * y + cx; y = 2 * x * y + cy; x = xTemp; iter++; } if (iter === maxIter) return -1; // Fractional iteration for smooth coloring return iter + 1 - Math.log(Math.log(x * x + y * y) / 2) / Math.log(2); } function draw() { const imageData = ctx.createImageData(width, height); const data = imageData.data; for (let py = 0; py < height; py++) { for (let px = 0; px < width; px++) { const cx = centerX + (px - width / 2) / zoom; const cy = centerY + (py - height / 2) / zoom; const m = mandelbrot(cx, cy); const idx = (py * width + px) * 4; if (m === -1) { data[idx] = data[idx + 1] = data[idx + 2] = 0; } else { const hue = (m * 10) % 360; const rgb = hslToRgb(hue / 360, 0.8, 0.5); data[idx] = rgb[0]; data[idx + 1] = rgb[1]; data[idx + 2] = rgb[2]; } data[idx + 3] = 255; } } ctx.putImageData(imageData, 0, 0); } function hslToRgb(h, s, l) { let r, g, b; if (s === 0) r = g = b = l; else { const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; } function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1/6) return p + (q - p) * 6 * t; if (t < 1/2) return q; if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; return p; } let isDragging = false; let lastMouseX, lastMouseY; canvas.addEventListener('mousedown', e => { isDragging = true; lastMouseX = e.clientX; lastMouseY = e.clientY; }); window.addEventListener('mouseup', () => isDragging = false); canvas.addEventListener('mousemove', e => { if (!isDragging) return; centerX -= (e.clientX - lastMouseX) / zoom; centerY -= (e.clientY - lastMouseY) / zoom; lastMouseX = e.clientX; lastMouseY = e.clientY; draw(); }); canvas.addEventListener('wheel', e => { e.preventDefault(); const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; zoom *= zoomFactor; maxIter = Math.floor(100 + Math.log10(zoom) * 50); draw(); }, { passive: false }); </script> </body> </html> ```
TAKE IT TO CODE
A single self-contained HTML file — copy it and open in any browser, or reuse the prompt with your own pi-agent run.
RUN
EVALUATION
Mandelbrot renders with smooth color gradient; drag pans and wheel zooms correctly; click/keys have no effect (expected).
Vision grade · anthropic/claude-sonnet-5
MEASUREMENTS
Raw readings from the capture, not a verdict — the grade above is the only judgement. Percentages are how much of the screen changed; the measure under-reports sparse motion on a dark background.