Xxx

Pasted Oct 3, 2026, 12:37 PM1 file347 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgt4vee6ravpm37
untitled
```html
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <title>Fraktal Mandelbrota</title>

    <style>
        html, body {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background: #000;
        }

        canvas {
            display: block;
            width: 100%;
            height: 100%;
            cursor: crosshair;
        }

        #info {
            position: fixed;
            top: 10px;
            left: 10px;
            color: white;
            font: 14px monospace;
            background: rgba(0, 0, 0, .65);
            padding: 8px 12px;
            border-radius: 5px;
            user-select: none;
        }
    </style>
</head>

<body>

<canvas id="canvas"></canvas>

<div id="info">
    Scroll = zoom<br>
    Lewy przycisk myszy = przesuwanie<br>
    R = reset
</div>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let width;
let height;

let centerX = -0.5;
let centerY = 0;

let scale = 3.0;

const MAX_ITERATIONS = 500;


// ---------------------------------------------------------
// Canvas
// ---------------------------------------------------------

function resize() {
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;

    draw();
}

window.addEventListener('resize', resize);


// ---------------------------------------------------------
// Konwersja piksel -> liczba zespolona
// ---------------------------------------------------------

function pixelToComplex(px, py) {

    const aspectRatio = width / height;

    const x =
        centerX +
        (px / width - 0.5) *
        scale *
        aspectRatio;

    const y =
        centerY +
        (py / height - 0.5) *
        scale;

    return { x, y };
}


// ---------------------------------------------------------
// Konwersja liczby zespolonej -> kolor
// ---------------------------------------------------------

function getColor(iterations, zx, zy) {

    if (iterations === MAX_ITERATIONS) {
        return [0, 0, 0];
    }

    /*
     * Smooth coloring.
     *
     * Dzięki temu zamiast prostych pasów kolorów
     * otrzymujemy płynne przejścia.
     */

    const magnitude = Math.sqrt(zx * zx + zy * zy);

    const smooth =
        iterations +
        1 -
        Math.log(Math.log(magnitude)) / Math.log(2);

    const t = smooth / MAX_ITERATIONS;

    const r = Math.floor(9 * (1 - t) * t * t * t * 255);
    const g = Math.floor(15 * (1 - t) * (1 - t) * t * t * 255);
    const b = Math.floor(8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255);

    return [r, g, b];
}


// ---------------------------------------------------------
// Mandelbrot
// ---------------------------------------------------------

function draw() {

    const image = ctx.createImageData(width, height);
    const data = image.data;

    const aspectRatio = width / height;

    let index = 0;

    for (let py = 0; py < height; py++) {

        const cy =
            centerY +
            (py / height - 0.5) *
            scale;

        for (let px = 0; px < width; px++) {

            const cx =
                centerX +
                (px / width - 0.5) *
                scale *
                aspectRatio;


            let zx = 0;
            let zy = 0;

            let iterations = 0;


            while (
                zx * zx + zy * zy <= 4 &&
                iterations < MAX_ITERATIONS
            ) {

                /*
                 * (zx + i*zy)^2 + (cx + i*cy)
                 */

                const zx2 =
                    zx * zx -
                    zy * zy +
                    cx;

                const zy2 =
                    2 * zx * zy +
                    cy;

                zx = zx2;
                zy = zy2;

                iterations++;
            }


            const [r, g, b] =
                getColor(iterations, zx, zy);

            data[index++] = r;
            data[index++] = g;
            data[index++] = b;
            data[index++] = 255;
        }
    }

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


// ---------------------------------------------------------
// Zoom
// ---------------------------------------------------------

canvas.addEventListener('wheel', event => {

    event.preventDefault();

    const rect = canvas.getBoundingClientRect();

    const mouseX =
        event.clientX - rect.left;

    const mouseY =
        event.clientY - rect.top;


    /*
     * Zapamiętujemy punkt pod kursorem
     * przed zmianą skali.
     */

    const before =
        pixelToComplex(mouseX, mouseY);


    const zoomFactor =
        event.deltaY < 0
            ? 0.8
            : 1.25;

    scale *= zoomFactor;


    /*
     * Po zmianie skali przesuwamy środek
     * tak, aby punkt znajdujący się
     * pod kursorem pozostał pod kursorem.
     */

    const after =
        pixelToComplex(mouseX, mouseY);

    centerX += before.x - after.x;
    centerY += before.y - after.y;


    draw();

}, { passive: false });


// ---------------------------------------------------------
// Panowanie
// ---------------------------------------------------------

let dragging = false;

let lastMouseX = 0;
let lastMouseY = 0;


canvas.addEventListener('mousedown', event => {

    dragging = true;

    lastMouseX = event.clientX;
    lastMouseY = event.clientY;
});


window.addEventListener('mouseup', () => {
    dragging = false;
});


window.addEventListener('mousemove', event => {

    if (!dragging) {
        return;
    }


    const dx =
        event.clientX - lastMouseX;

    const dy =
        event.clientY - lastMouseY;


    const aspectRatio =
        width / height;


    centerX -=
        dx / width *
        scale *
        aspectRatio;

    centerY -=
        dy / height *
        scale;


    lastMouseX = event.clientX;
    lastMouseY = event.clientY;


    draw();
});


// ---------------------------------------------------------
// Reset
// ---------------------------------------------------------

window.addEventListener('keydown', event => {

    if (event.key.toLowerCase() === 'r') {

        centerX = -0.5;
        centerY = 0;
        scale = 3;

        draw();
    }
});


// ---------------------------------------------------------
// Start
// ---------------------------------------------------------

resize();
</script>

</body>
</html>
```

6,452 chars · codepastes.com