Realtidsrendering av mandelbrotmängden

Här är en realtidsrendering av mandelbrotsmängden skriven i HTML5/JS. Jag har själv en ganska slö dator, så jag ökar aldrig antalet iterationer till mer än 800, men det är lätt att korrigera. Zooma med mushjulet, panorera genom att klicka och dra. Så här ser källkoden ut:


<!DOCTYPE html>
<html lang="sv">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <title>Mandelbrot med zoom och panorering</title>
    <style>
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
        }

        body {
            display: flex;
            justify-content: center;
            -ms-align-items: center;
            -o-align-items: center;
            -webkit-align-items: center;
            align-items: center;
            background: #0000aa;
        }

        canvas {
            border: 1px solid #4466ff;
            display: block;
            margin: auto;
            background: #000000;
            cursor: grab;
        }

        canvas:active {
            cursor: grabbing;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="640" height="400"></canvas>
    <script>
        const canvas = document.getElementById("canvas");
        const ctx = canvas.getContext("2d");
        let width = canvas.width;
        let height = canvas.height;
        let xMin = -2.5, xMax = 1;
        let yMin = -1.25, yMax = 1.25;
        var maxIterations = 50;
        let isDragging = false;
        let dragStartX, dragStartY;
        let dragStartXmin, dragStartXmax, dragStartYmin, dragStartYmax;

        function drawMandelbrot() {
            const img = ctx.createImageData(width, height);
            const data = img.data;

            for (let py = 0; py < height; py++) {
                const y0 = yMin + (py / height) * (yMax - yMin);

                for (let px = 0; px < width; px++) {
                    const x0 = xMin + (px / width) * (xMax - xMin);
                    let x = 0, y = 0, iteration = 0;

                    while (x * x + y * y <= 4 && iteration < maxIterations) {
                        const xTemp = x * x - y * y + x0;
                        y = 2 * x * y + y0;
                        x = xTemp;
                        iteration++;
                    }

                    const color = iteration === maxIterations ? 0 : 255 - Math.floor(iteration * 255 / maxIterations);
                    const index = 4 * (py * width + px);
                    data[index] = color;
                    data[index + 1] = color;
                    data[index + 2] = color;
                    data[index + 3] = 255;
                }
            }

            ctx.putImageData(img, 0, 0);
        }

        drawMandelbrot();

        canvas.addEventListener("wheel", function (event) {
            event.preventDefault();
            const mouseX = event.offsetX;
            const mouseY = event.offsetY;
            const zoomFactor = event.deltaY < 0 ? 0.9 : 1.1;

            if (zoomFactor < 1.0) {
                maxIterations += 2;
            } else {
                maxIterations -= 2;
            }

            if (maxIterations < 30) {
                maxIterations = 30;
            }
            else if (maxIterations > 800) {
                maxIterations = 800
            }

            const xCenter = xMin + (mouseX / width) * (xMax - xMin);
            const yCenter = yMin + (mouseY / height) * (yMax - yMin);
            const newWidth = (xMax - xMin) * zoomFactor;
            const newHeight = (yMax - yMin) * zoomFactor;
            xMin = xCenter - (mouseX / width) * newWidth;
            xMax = xMin + newWidth;
            yMin = yCenter - (mouseY / height) * newHeight;
            yMax = yMin + newHeight;
            drawMandelbrot();
        });

        canvas.addEventListener("mousedown", function (event) {
            isDragging = true;
            dragStartX = event.offsetX;
            dragStartY = event.offsetY;
            dragStartXmin = xMin;
            dragStartXmax = xMax;
            dragStartYmin = yMin;
            dragStartYmax = yMax;
        });

        canvas.addEventListener("mousemove", function (event) {
            if (!isDragging)
                return;

            const dx = event.offsetX - dragStartX;
            const dy = event.offsetY - dragStartY;
            const xShift = (dx / width) * (dragStartXmax - dragStartXmin);
            const yShift = (dy / height) * (dragStartYmax - dragStartYmin);
            xMin = dragStartXmin - xShift;
            xMax = dragStartXmax - xShift;
            yMin = dragStartYmin - yShift;
            yMax = dragStartYmax - yShift;
            drawMandelbrot();
        });

        canvas.addEventListener("mouseup", () => { isDragging = false; });
        canvas.addEventListener("mouseleave", () => { isDragging = false; });
    </script>
</body>
</html>

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll:

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!

Comments

Important information: If you have not commented before, your comment will be reviewed before it is published. This means that you will not see it immediately, but I have received it. This is not because I want to filter comments, but because I want to prevent spam and advertising.

Leave a Reply

Your email address will not be published. Required fields are marked *