Revert "Fix startup freeze on weak devices and add Vercel Analytics"
This reverts commit b1de6a8e56.
This commit is contained in:
@@ -173,9 +173,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
|
||||||
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
|
|
||||||
</script>
|
|
||||||
<script defer src="/_vercel/insights/script.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+1
-8
@@ -20,7 +20,7 @@
|
|||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@500;600&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@500;600&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="styles.css" />
|
<link rel="stylesheet" href="styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body class="booting">
|
<body>
|
||||||
|
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div class="brand">
|
<div class="brand">
|
||||||
@@ -69,11 +69,8 @@
|
|||||||
<main class="app">
|
<main class="app">
|
||||||
<section class="stage" id="stage">
|
<section class="stage" id="stage">
|
||||||
<div class="canvas-frame" id="canvas-frame">
|
<div class="canvas-frame" id="canvas-frame">
|
||||||
<div class="canvas-shell" id="canvas-shell">
|
|
||||||
<div class="canvas-boot" id="canvas-boot" aria-hidden="true"></div>
|
|
||||||
<canvas id="view"></canvas>
|
<canvas id="view"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="stage-meta">
|
<div class="stage-meta">
|
||||||
<div class="meta-left">
|
<div class="meta-left">
|
||||||
<button class="icon-btn" id="btn-play" title="Play / pause (Space)">
|
<button class="icon-btn" id="btn-play" title="Play / pause (Space)">
|
||||||
@@ -119,9 +116,5 @@
|
|||||||
<script src="js/modals.js"></script>
|
<script src="js/modals.js"></script>
|
||||||
<script src="js/ui.js"></script>
|
<script src="js/ui.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
<script>
|
|
||||||
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
|
|
||||||
</script>
|
|
||||||
<script defer src="/_vercel/insights/script.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+2
-14
@@ -5,7 +5,6 @@ var Engine = (function () {
|
|||||||
var canvas, gl, program, uniforms = {};
|
var canvas, gl, program, uniforms = {};
|
||||||
var playing = true;
|
var playing = true;
|
||||||
var suspended = false;
|
var suspended = false;
|
||||||
var started = false;
|
|
||||||
var loopT = 0; // seconds into current loop
|
var loopT = 0; // seconds into current loop
|
||||||
var lastTick = 0;
|
var lastTick = 0;
|
||||||
var fps = 60, fpsAcc = 0, fpsN = 0, fpsCb = null;
|
var fps = 60, fpsAcc = 0, fpsN = 0, fpsCb = null;
|
||||||
@@ -33,14 +32,13 @@ var Engine = (function () {
|
|||||||
return sh;
|
return sh;
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(canvasEl, paramsGetter, opts) {
|
function init(canvasEl, paramsGetter) {
|
||||||
opts = opts || {};
|
|
||||||
canvas = canvasEl;
|
canvas = canvasEl;
|
||||||
getParams = paramsGetter;
|
getParams = paramsGetter;
|
||||||
gl = canvas.getContext("webgl2", {
|
gl = canvas.getContext("webgl2", {
|
||||||
antialias: false,
|
antialias: false,
|
||||||
preserveDrawingBuffer: true,
|
preserveDrawingBuffer: true,
|
||||||
powerPreference: "default"
|
powerPreference: "high-performance"
|
||||||
});
|
});
|
||||||
if (!gl) throw new Error("WebGL2 not available");
|
if (!gl) throw new Error("WebGL2 not available");
|
||||||
|
|
||||||
@@ -63,15 +61,6 @@ var Engine = (function () {
|
|||||||
uniforms[n] = gl.getUniformLocation(program, n);
|
uniforms[n] = gl.getUniformLocation(program, n);
|
||||||
});
|
});
|
||||||
|
|
||||||
lastTick = performance.now();
|
|
||||||
started = false;
|
|
||||||
if (opts.autostart) start();
|
|
||||||
}
|
|
||||||
|
|
||||||
function start() {
|
|
||||||
if (started) return;
|
|
||||||
started = true;
|
|
||||||
suspended = false;
|
|
||||||
lastTick = performance.now();
|
lastTick = performance.now();
|
||||||
requestAnimationFrame(tick);
|
requestAnimationFrame(tick);
|
||||||
}
|
}
|
||||||
@@ -179,7 +168,6 @@ var Engine = (function () {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
start: start,
|
|
||||||
setSize: setSize,
|
setSize: setSize,
|
||||||
renderAt: renderAt,
|
renderAt: renderAt,
|
||||||
readPixels: readPixels,
|
readPixels: readPixels,
|
||||||
|
|||||||
+65
-85
@@ -483,7 +483,7 @@ function updateMeta() {
|
|||||||
document.getElementById("meta-res").textContent = s[0] + "\u00d7" + s[1];
|
document.getElementById("meta-res").textContent = s[0] + "\u00d7" + s[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function fitCanvas(preview) {
|
function fitCanvas() {
|
||||||
var frame = document.getElementById("canvas-frame");
|
var frame = document.getElementById("canvas-frame");
|
||||||
var availW = frame.clientWidth - 80;
|
var availW = frame.clientWidth - 80;
|
||||||
var availH = frame.clientHeight - 52;
|
var availH = frame.clientHeight - 52;
|
||||||
@@ -491,18 +491,10 @@ function fitCanvas(preview) {
|
|||||||
var ar = ASPECTS[P.aspect];
|
var ar = ASPECTS[P.aspect];
|
||||||
var w = availW, h = w / ar;
|
var w = availW, h = w / ar;
|
||||||
if (h > availH) { h = availH; w = h * ar; }
|
if (h > availH) { h = availH; w = h * ar; }
|
||||||
w = Math.round(w);
|
|
||||||
h = Math.round(h);
|
|
||||||
var canvas = Engine.canvas();
|
var canvas = Engine.canvas();
|
||||||
canvas.style.width = w + "px";
|
canvas.style.width = Math.round(w) + "px";
|
||||||
canvas.style.height = h + "px";
|
canvas.style.height = Math.round(h) + "px";
|
||||||
var boot = document.getElementById("canvas-boot");
|
var dpr = Math.min(window.devicePixelRatio || 1, 1.35);
|
||||||
if (boot) {
|
|
||||||
boot.style.width = w + "px";
|
|
||||||
boot.style.height = h + "px";
|
|
||||||
}
|
|
||||||
var dprCap = preview ? 0.75 : 1.35;
|
|
||||||
var dpr = Math.min(window.devicePixelRatio || 1, dprCap);
|
|
||||||
Engine.setSize(2 * Math.round(w * dpr / 2), 2 * Math.round(h * dpr / 2));
|
Engine.setSize(2 * Math.round(w * dpr / 2), 2 * Math.round(h * dpr / 2));
|
||||||
updateMeta();
|
updateMeta();
|
||||||
}
|
}
|
||||||
@@ -515,22 +507,71 @@ function setPlayingUI(v) {
|
|||||||
|
|
||||||
/* ---------------- boot ---------------- */
|
/* ---------------- boot ---------------- */
|
||||||
|
|
||||||
function runIntro() {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
var canvas = document.getElementById("view");
|
||||||
|
try {
|
||||||
|
Engine.init(canvas, function () { return P; });
|
||||||
|
} catch (e) {
|
||||||
|
document.querySelector(".canvas-frame").innerHTML =
|
||||||
|
'<div style="color:#9b9ba4;font-size:13px;max-width:380px;text-align:center;line-height:1.6">' +
|
||||||
|
"WebGL2 is required. Please use a recent Chrome, Edge or Firefox.<br><span style=\"color:#5e5e68;font-size:11px\">" +
|
||||||
|
String(e.message).split("\n")[0] + "</span></div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildRail();
|
||||||
|
|
||||||
|
/* aspect segmented control */
|
||||||
|
var segRefresh = UI.segmented(
|
||||||
|
document.getElementById("aspect-seg"),
|
||||||
|
Object.keys(ASPECTS).map(function (k) { return [k, k]; }),
|
||||||
|
get("aspect"),
|
||||||
|
function (v) { P.aspect = v; fitCanvas(); }
|
||||||
|
);
|
||||||
|
reg(segRefresh);
|
||||||
|
|
||||||
|
/* load a shared design from the URL hash, e.g. .../#LMN1.xxxx */
|
||||||
|
var hash = decodeURIComponent(location.hash.slice(1) || "");
|
||||||
|
if (hash.indexOf("LMN1.") === 0 && decodeDesign(hash)) {
|
||||||
|
UI.toast("Shared design loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
fitCanvas();
|
||||||
|
new ResizeObserver(fitCanvas).observe(document.getElementById("canvas-frame"));
|
||||||
|
|
||||||
|
/* load a shared design from the URL hash, e.g. site/#LMN1.xxxx */
|
||||||
|
if (location.hash.length > 6) {
|
||||||
|
if (decodeDesign(decodeURIComponent(location.hash.slice(1)))) {
|
||||||
|
UI.toast("Shared design loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* intro: every element pops in big and settles into place,
|
||||||
|
one after another. transform/opacity only, fully compositor-driven. */
|
||||||
|
(function intro() {
|
||||||
var items = [];
|
var items = [];
|
||||||
document.querySelectorAll(".brand, .segmented button, .topbar-actions > *").forEach(function (n) {
|
document.querySelectorAll(".brand, .segmented button, .topbar-actions > *").forEach(function (n) { items.push(n); });
|
||||||
items.push(n);
|
items.push(document.querySelector(".canvas-frame"));
|
||||||
});
|
|
||||||
items.push(document.getElementById("canvas-shell"));
|
|
||||||
items.push(document.querySelector(".stage-meta"));
|
items.push(document.querySelector(".stage-meta"));
|
||||||
document.querySelectorAll(".rail-section").forEach(function (n) { items.push(n); });
|
document.querySelectorAll(".rail-section").forEach(function (sec) {
|
||||||
document.querySelectorAll(".mode-grid > *, .export-grid > *").forEach(function (n) { items.push(n); });
|
Array.prototype.forEach.call(sec.children, function (child) {
|
||||||
|
if (child.classList.contains("mode-grid") ||
|
||||||
|
child.classList.contains("preset-row") ||
|
||||||
|
child.classList.contains("export-grid")) {
|
||||||
|
Array.prototype.forEach.call(child.children, function (n) { items.push(n); });
|
||||||
|
} else {
|
||||||
|
items.push(child);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var d = 0;
|
var d = 0;
|
||||||
items.forEach(function (n, i) {
|
items.forEach(function (n, i) {
|
||||||
if (!n) return;
|
if (!n) return;
|
||||||
d += i < 10 ? 40 : 24;
|
/* fast cadence inside the rail, slower for the hero pieces */
|
||||||
|
d += i < 12 ? 50 : 16;
|
||||||
n.classList.add("stagger-item");
|
n.classList.add("stagger-item");
|
||||||
n.style.setProperty("--intro-d", Math.min(d, 820) + "ms");
|
n.style.setProperty("--intro-d", Math.min(d, 2100) + "ms");
|
||||||
});
|
});
|
||||||
document.body.classList.add("intro");
|
document.body.classList.add("intro");
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@@ -539,18 +580,10 @@ function runIntro() {
|
|||||||
if (!n) return;
|
if (!n) return;
|
||||||
n.classList.remove("stagger-item");
|
n.classList.remove("stagger-item");
|
||||||
n.style.removeProperty("--intro-d");
|
n.style.removeProperty("--intro-d");
|
||||||
|
n.style.willChange = "auto";
|
||||||
});
|
});
|
||||||
}, 1500);
|
}, 3000);
|
||||||
}
|
})();
|
||||||
|
|
||||||
function wireControls() {
|
|
||||||
var segRefresh = UI.segmented(
|
|
||||||
document.getElementById("aspect-seg"),
|
|
||||||
Object.keys(ASPECTS).map(function (k) { return [k, k]; }),
|
|
||||||
get("aspect"),
|
|
||||||
function (v) { P.aspect = v; fitCanvas(); }
|
|
||||||
);
|
|
||||||
reg(segRefresh);
|
|
||||||
|
|
||||||
Engine.onFps(function (fps) {
|
Engine.onFps(function (fps) {
|
||||||
document.getElementById("meta-fps").textContent = fps + " fps";
|
document.getElementById("meta-fps").textContent = fps + " fps";
|
||||||
@@ -572,59 +605,6 @@ function wireControls() {
|
|||||||
else if (e.key === "r" || e.key === "R") { randomizeAll(); }
|
else if (e.key === "r" || e.key === "R") { randomizeAll(); }
|
||||||
else if (e.key === "s" || e.key === "S") { Exporter.exportPNG(P, ASPECTS[P.aspect]); }
|
else if (e.key === "s" || e.key === "S") { Exporter.exportPNG(P, ASPECTS[P.aspect]); }
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
function showBootError(msg) {
|
|
||||||
document.body.classList.remove("booting");
|
|
||||||
document.querySelector(".canvas-frame").innerHTML =
|
|
||||||
'<div style="color:#9b9ba4;font-size:13px;max-width:380px;text-align:center;line-height:1.6">' +
|
|
||||||
"WebGL2 is required. Please use a recent Chrome, Edge or Firefox.<br><span style=\"color:#5e5e68;font-size:11px\">" +
|
|
||||||
String(msg).split("\n")[0] + "</span></div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
function finishBoot(opts) {
|
|
||||||
document.body.classList.remove("booting");
|
|
||||||
document.body.classList.add("ready");
|
|
||||||
Engine.start();
|
|
||||||
if (opts.intro) runIntro();
|
|
||||||
setTimeout(function () { fitCanvas(false); }, 1400);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
var canvas = document.getElementById("view");
|
|
||||||
var lowPower = (navigator.hardwareConcurrency || 8) <= 4 ||
|
|
||||||
((navigator.deviceMemory || 8) <= 4);
|
|
||||||
var reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
||||||
|
|
||||||
/* paint the shell first, then build UI, then compile shaders off the first frame */
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
buildRail();
|
|
||||||
wireControls();
|
|
||||||
|
|
||||||
var hash = decodeURIComponent(location.hash.slice(1) || "");
|
|
||||||
if (hash.indexOf("LMN1.") === 0 && decodeDesign(hash)) {
|
|
||||||
UI.toast("Shared design loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
fitCanvas(true);
|
|
||||||
new ResizeObserver(function () {
|
|
||||||
fitCanvas(!document.body.classList.contains("ready"));
|
|
||||||
}).observe(document.getElementById("canvas-frame"));
|
|
||||||
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
try {
|
|
||||||
Engine.init(canvas, function () { return P; }, { autostart: false });
|
|
||||||
} catch (e) {
|
|
||||||
showBootError(e.message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Engine.renderAt(0);
|
|
||||||
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
finishBoot({ intro: !lowPower && !reduceMotion });
|
|
||||||
updateMeta();
|
updateMeta();
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
+5
-57
@@ -189,38 +189,6 @@ button { font: inherit; color: inherit; cursor: pointer; background: none; borde
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.canvas-shell {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-boot {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: var(--radius-l);
|
|
||||||
background:
|
|
||||||
linear-gradient(135deg, #120804 0%, #3d1204 38%, #ff6a00 72%, #ffb347 100%);
|
|
||||||
background-size: 220% 220%;
|
|
||||||
animation: boot-shimmer 2.2s ease-in-out infinite;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(255,255,255,0.07),
|
|
||||||
inset 0 1px 0 rgba(255,255,255,0.08),
|
|
||||||
0 30px 80px -20px rgba(0,0,0,0.9),
|
|
||||||
0 8px 26px -10px rgba(0,0,0,0.65);
|
|
||||||
transition: opacity 0.45s ease;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes boot-shimmer {
|
|
||||||
0%, 100% { background-position: 0% 50%; }
|
|
||||||
50% { background-position: 100% 50%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
body.ready .canvas-boot { opacity: 0; }
|
|
||||||
|
|
||||||
#view {
|
#view {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
@@ -231,12 +199,8 @@ body.ready .canvas-boot { opacity: 0; }
|
|||||||
0 30px 80px -20px rgba(0,0,0,0.9),
|
0 30px 80px -20px rgba(0,0,0,0.9),
|
||||||
0 8px 26px -10px rgba(0,0,0,0.65);
|
0 8px 26px -10px rgba(0,0,0,0.65);
|
||||||
background: #000;
|
background: #000;
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.45s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body.ready #view { opacity: 1; }
|
|
||||||
|
|
||||||
.stage-meta {
|
.stage-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -854,35 +818,19 @@ select { cursor: pointer; appearance: none; padding-right: 22px;
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- boot: keep shell visible, defer heavy glass ---------- */
|
|
||||||
|
|
||||||
body.booting .topbar,
|
|
||||||
body.booting .rail {
|
|
||||||
backdrop-filter: none;
|
|
||||||
-webkit-backdrop-filter: none;
|
|
||||||
}
|
|
||||||
body.booting .topbar { background: var(--bg); }
|
|
||||||
body.booting .rail {
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
body.ready .rail {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: auto;
|
|
||||||
transition: opacity 0.35s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- intro stagger animation ---------- */
|
/* ---------- intro stagger animation ---------- */
|
||||||
|
|
||||||
@keyframes intro-pop {
|
@keyframes intro-pop {
|
||||||
0% { opacity: 0; transform: scale(1.1) translateY(6px); }
|
0% { opacity: 0; transform: scale(1.45) translateY(-4px); }
|
||||||
|
62% { opacity: 1; }
|
||||||
100% { opacity: 1; transform: scale(1) translateY(0); }
|
100% { opacity: 1; transform: scale(1) translateY(0); }
|
||||||
}
|
}
|
||||||
.intro .stagger-item {
|
.intro .stagger-item {
|
||||||
animation: intro-pop 420ms cubic-bezier(.22,1,.36,1) both;
|
animation: intro-pop 560ms cubic-bezier(.22,1.3,.36,1) both;
|
||||||
animation-delay: var(--intro-d, 0ms);
|
animation-delay: var(--intro-d, 0ms);
|
||||||
|
will-change: transform, opacity;
|
||||||
}
|
}
|
||||||
.intro .canvas-shell.stagger-item { animation-duration: 520ms; }
|
.intro .canvas-frame.stagger-item { animation-duration: 780ms; }
|
||||||
|
|
||||||
/* ---------- download success effect ---------- */
|
/* ---------- download success effect ---------- */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user