← Fractal Explorer results

Fractal Explorer

Qwen 3.6 27B MTP GGUF · typescript

Initial view of Fractal Explorer

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 11,792 bytes · SHA-256 260fcc8e2198
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fractal Explorer</title>
<style>
/* ── css: layout ── */
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; font-family: 'Segoe UI', system-ui, sans-serif; }
#app { position: relative; width: 100%; height: 100%; }
#fractal { display: block; width: 100%; height: 100%; cursor: crosshair; }

/* HUD */
#hud { position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; transition: opacity 0.5s; }
#hud.hidden { opacity: 0; }
#hud-top { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); display: flex; gap: 16px; padding: 8px 16px; background: rgba(0,0,0,0.55); backdrop-filter: blur(8px); border-radius: 8px; color: #ccc; font-size: 13px; font-family: 'SF Mono', 'Consolas', monospace; pointer-events: auto; }
#hud-bottom { position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; gap: 8px; pointer-events: auto; }
#palette-bar { display: flex; gap: 6px; justify-content: center; }
.palette-swatch { width: 28px; height: 28px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.3); cursor: pointer; transition: transform 0.15s, border-color 0.15s; }
.palette-swatch:hover { transform: scale(1.15); }
.palette-swatch.active { border-color: #fff; transform: scale(1.15); }
#controls-bar { display: flex; gap: 8px; align-items: center; padding: 6px 12px; background: rgba(0,0,0,0.55); backdrop-filter: blur(8px); border-radius: 8px; color: #ccc; font-size: 12px; }
#controls-bar button { background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: #ddd; padding: 4px 10px; border-radius: 4px; cursor: pointer; font-size: 14px; }
#controls-bar button:hover { background: rgba(255,255,255,0.2); }
#controls-bar button.active { background: rgba(100,200,255,0.3); border-color: rgba(100,200,255,0.6); }
#controls-bar input[type=range] { width: 80px; height: 4px; }
#iter-control, #palette-offset-control { display: flex; align-items: center; gap: 4px; color: #aaa; font-size: 11px; }
#bookmarks-list { display: flex; gap: 4px; align-items: center; }
.bookmark-btn { background: rgba(255,255,100,0.15); border: 1px solid rgba(255,255,100,0.4); color: #ffd700; padding: 2px 8px; border-radius: 4px; cursor: pointer; font-size: 11px; }
.bookmark-btn:hover { background: rgba(255,255,100,0.3); }

/* Julia preview */
#julia-preview { position: absolute; top: 12px; right: 12px; border: 2px solid rgba(255,255,255,0.3); border-radius: 8px; overflow: hidden; background: #000; }
#julia-canvas { display: block; }
#julia-label { position: absolute; top: 4px; left: 8px; color: rgba(255,255,255,0.7); font-size: 11px; font-family: monospace; }

/* Zoom box overlay */
#zoom-box { position: absolute; border: 1px dashed rgba(255,255,255,0.7); pointer-events: none; display: none; }
</style>
</head>
<body>
<div id="app">
  <canvas id="fractal"></canvas>
  <div id="hud">
    <div id="hud-top">
      <div id="mag-display">×1.0</div>
      <div id="coord-display">0.000 + 0.000i</div>
      <div id="iter-display">iter: 256</div>
      <div id="fps-display">60 fps</div>
    </div>
    <div id="hud-bottom">
      <div id="palette-bar"></div>
      <div id="controls-bar">
        <button id="btn-reset" title="Reset View">⟲</button>
        <button id="btn-back" title="Zoom Back">←</button>
        <button id="btn-julia" title="Toggle Julia Mode">J</button>
        <button id="btn-bookmark" title="Save Bookmark">★</button>
        <div id="bookmarks-list"></div>
        <div id="iter-control">
          <label>Iter: <input id="iter-slider" type="range" min="50" max="10000" value="256"></label>
          <span id="iter-val">256</span>
        </div>
        <div id="palette-offset-control">
          <label>Shift: <input id="palette-slider" type="range" min="0" max="1000" value="0"></label>
        </div>
      </div>
    </div>
  </div>
  <div id="julia-preview" style="display:none">
    <canvas id="julia-canvas"></canvas>
    <div id="julia-label">Julia Set</div>
  </div>
</div>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {"src/palettes.ts":{"./config":"src/config.ts"},"src/state.ts":{"./config":"src/config.ts"}};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
// Entry point. Runs after the DOM is parsed and after any classic
// <script> imports, so document queries and CDN globals are available.
// Import your other modules from here.
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = start;
function start() {
    // Replace this with the real startup sequence.
}
start();
};

// ── module: src/config.ts ──
__mods["src/config.ts"] = function (exports, require, module) {
"use strict";
// Tunable constants for the fractal explorer
Object.defineProperty(exports, "__esModule", { value: true });
exports.CONFIG = void 0;
exports.CONFIG = {
    // Iteration settings
    maxIterBase: 256,
    maxIterScale: 50, // extra iterations per log10 of magnification
    maxIterCap: 10000,
    maxIterMin: 50,
    // Precision limits
    maxMagnification: 1e14,
    // Zoom settings
    zoomFactor: 2.0,
    wheelZoomSpeed: 0.001,
    dragZoomMinSize: 3, // minimum pixels for drag-zoom
    // Progressive rendering
    progressiveSteps: [4, 2, 1], // downsample factors: coarse → fine → full
    renderChunkSize: 5000, // pixels per chunk (for non-blocking)
    // Julia preview
    juliaPreviewSize: 200, // px
    juliaPreviewIter: 256,
    // HUD
    hudHideDelay: 3000, // ms of inactivity before hiding
    // Color
    escapeRadius: 256, // |z|^2 threshold for escape (256 = 16^2)
    smoothColoring: true,
};
};

// ── module: src/palettes.ts ──
__mods["src/palettes.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PALETTE_LUT_SIZE = exports.PALETTES = void 0;
exports.buildPaletteLuts = buildPaletteLuts;
exports.getColor = getColor;
exports.PALETTES = [
    {
        name: 'Fire',
        preview: 'linear-gradient(90deg, #000, #f00, #ff0, #fff)',
        stops: [
            { t: 0.0, r: 0, g: 0, b: 0 },
            { t: 0.2, r: 128, g: 0, b: 0 },
            { t: 0.4, r: 255, g: 80, b: 0 },
            { t: 0.6, r: 255, g: 220, b: 50 },
            { t: 0.8, r: 255, g: 255, b: 200 },
            { t: 1.0, r: 255, g: 255, b: 255 },
        ],
    },
    {
        name: 'Ocean',
        preview: 'linear-gradient(90deg, #001, #00a, #0af, #fff)',
        stops: [
            { t: 0.0, r: 0, g: 5, b: 20 },
            { t: 0.2, r: 0, g: 20, b: 80 },
            { t: 0.4, r: 0, g: 60, b: 180 },
            { t: 0.6, r: 0, g: 180, b: 220 },
            { t: 0.8, r: 100, g: 230, b: 255 },
            { t: 1.0, r: 220, g: 255, b: 255 },
        ],
    },
    {
        name: 'Mono',
        preview: 'linear-gradient(90deg, #000, #666, #fff)',
        stops: [
            { t: 0.0, r: 0, g: 0, b: 0 },
            { t: 0.5, r: 128, g: 128, b: 128 },
            { t: 1.0, r: 255, g: 255, b: 255 },
        ],
    },
    {
        name: 'Psychedelic',
        preview: 'linear-gradient(90deg, #f0f, #0ff, #ff0, #f0f)',
        stops: [
            { t: 0.0, r: 200, g: 0, b: 200 },
            { t: 0.25, r: 0, g: 200, b: 200 },
            { t: 0.5, r: 200, g: 200, b: 0 },
            { t: 0.75, r: 0, g: 200, b: 0 },
            { t: 1.0, r: 200, g: 0, b: 200 },
        ],
    },
    {
        name: 'Electric',
        preview: 'linear-gradient(90deg, #000, #a0f, #0af, #f0a)',
        stops: [
            { t: 0.0, r: 0, g: 0, b: 0 },
            { t: 0.3, r: 80, g: 0, b: 200 },
            { t: 0.5, r: 0, g: 150, b: 255 },
            { t: 0.7, r: 200, g: 50, b: 150 },
            { t: 1.0, r: 0, g: 0, b: 0 },
        ],
    },
];
// Precompute palette LUT for fast colorization (256 entries per palette)
exports.PALETTE_LUT_SIZE = 2048;
const paletteLuts = [];
function buildPaletteLuts() {
    paletteLuts.length = 0;
    for (const pal of exports.PALETTES) {
        const lut = new Uint8Array(exports.PALETTE_LUT_SIZE * 3);
        for (let i = 0; i < exports.PALETTE_LUT_SIZE; i++) {
            const t = i / exports.PALETTE_LUT_SIZE;
            const [r, g, b] = interpolatePalette(pal.stops, t);
            const idx = i * 3;
            lut[idx] = r;
            lut[idx + 1] = g;
            lut[idx + 2] = b;
        }
        paletteLuts.push(Array.from(lut));
    }
}
function interpolatePalette(stops, t) {
    // Wrap t to [0, 1] cyclically
    t = t - Math.floor(t);
    if (t <= stops[0].t) {
        const s = stops[0];
        return [s.r, s.g, s.b];
    }
    if (t >= stops[stops.length - 1].t) {
        const s = stops[stops.length - 1];
        return [s.r, s.g, s.b];
    }
    for (let i = 0; i < stops.length - 1; i++) {
        const a = stops[i];
        const b = stops[i + 1];
        if (t >= a.t && t <= b.t) {
            const f = (t - a.t) / (b.t - a.t);
            const sf = f * f * (3 - 2 * f); // smoothstep
            return [
                Math.round(a.r + (b.r - a.r) * sf),
                Math.round(a.g + (b.g - a.g) * sf),
                Math.round(a.b + (b.b - a.b) * sf),
            ];
        }
    }
    return [0, 0, 0];
}
// Get color for a smooth iteration count
// smoothIter: the continuous iteration count (e.g. 42.7)
// paletteIdx: index into PALETTES
// offset: palette cycling offset (0..1)
function getColor(smoothIter, paletteIdx, offset, maxIter) {
    if (smoothIter >= maxIter) {
        return [0, 0, 0]; // interior point = black
    }
    const lut = paletteLuts[paletteIdx];
    if (!lut)
        return [0, 0, 0];
    // Map smooth iteration to color: use log-based mapping for better distribution
    // log(log(|z|)) gives a smooth value; we use the fractional part of iter / someScale
    const log2 = Math.log(2);
    const colorVal = smoothIter + offset;
    const t = (colorVal * 0.01) % 1.0; // cycle through palette
    const idx = Math.floor(t * (exports.PALETTE_LUT_SIZE - 1));
    const clampedIdx = Math.min(idx, exports.PALETTE_LUT_SIZE - 1);
    const lutIdx = clampedIdx * 3;
    return [lut[lutIdx], lut[lutIdx + 1], lut[lutIdx + 2]];
}
buildPaletteLuts();
};

// ── module: src/state.ts ──
__mods["src/state.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_STATE = void 0;
exports.computeMaxIter = computeMaxIter;
const config_1 = require("./config");
exports.DEFAULT_STATE = {
    re: -0.5,
    im: 0.0,
    scale: 1.0,
    maxIter: config_1.CONFIG.maxIterBase,
    paletteIdx: 0,
    paletteOffset: 0,
    mode: 'mandelbrot',
    juliaCRe: -0.7269,
    juliaCIm: 0.1889,
};
// Compute dynamic iteration count based on zoom depth
function computeMaxIter(scale) {
    const logScale = Math.log10(Math.max(scale, 1));
    const extra = Math.floor(logScale * config_1.CONFIG.maxIterScale);
    return Math.min(config_1.CONFIG.maxIterCap, Math.max(config_1.CONFIG.maxIterMin, config_1.CONFIG.maxIterBase + extra));
}
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>