Fractal Explorer
Qwen 3.6 27B MTP GGUF · typescript

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>