aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/viewer/tools/smoke/blend.mjs
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
committergodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
commit3443c1c65e9f1753e1e656b35d08416c1fa298f2 (patch)
tree4e43236f460145a4d75d1b4616dcb7aa6ef08f51 /viewer/tools/smoke/blend.mjs
downloadworldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.tar.gz
worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.zip
worldmap-viewer: initial public history
Diffstat (limited to 'viewer/tools/smoke/blend.mjs')
-rw-r--r--viewer/tools/smoke/blend.mjs20
1 files changed, 20 insertions, 0 deletions
diff --git a/viewer/tools/smoke/blend.mjs b/viewer/tools/smoke/blend.mjs
new file mode 100644
index 0000000..16d0dc6
--- /dev/null
+++ b/viewer/tools/smoke/blend.mjs
@@ -0,0 +1,20 @@
+// blend.mjs — a second layer drawn over the first, opacity slider, URL state
+const px = `const a = window.mapViewer, gl = a.renderer.getContext(); a.view.render(); const p = new Uint8Array(4);
+ gl.readPixels(gl.drawingBufferWidth >> 1, gl.drawingBufferHeight >> 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, p); return [...p.slice(0, 3)];`;
+const set = (id, v, ev = 'change') => `const s = document.getElementById('${id}'); s.value = '${v}'; s.dispatchEvent(new Event('${ev}'));
+ await new Promise(r => setTimeout(r, 1500));`;
+const close = (a, b, tol = 4) => a.every((x, i) => Math.abs(x - b[i]) <= tol);
+export const steps = [
+ { name: 'relief pixel', wait: 4000, js: `window.mapViewer.view.setState({ lat: 40, lon: 10, alt: 1.5 }); await new Promise(r => setTimeout(r, 500)); window.__r = (() => { ${px} })(); return window.__r;` },
+ { name: 'biomes pixel', js: set('layer', 'biomes') + `window.__b = (() => { ${px} })(); return window.__b;` },
+ { name: 'back to relief', js: set('layer', 'relief') + `const p = (() => { ${px} })(); return [p, window.__r];`, expect: ([p, r]) => close(p, r) },
+ { name: 'over = biomes shows the slider', js: set('over', 'biomes') + `return !document.getElementById('opacity').hidden;`, expect: v => v === true },
+ { name: 'opacity 100 → biomes', js: set('opacity', '100', 'input') + `const p = (() => { ${px} })(); return [p, window.__b];`, expect: ([p, b]) => close(p, b) },
+ { name: 'opacity 0 → relief', js: set('opacity', '0', 'input') + `const p = (() => { ${px} })(); return [p, window.__r];`, expect: ([p, r]) => close(p, r) },
+ { name: 'URL keeps over and op', js: set('opacity', '40', 'input') + `await new Promise(r => setTimeout(r, 400)); return location.hash;`,
+ expect: v => v.includes('over=biomes') && v.includes('op=0.4') },
+ { name: 'flat view blends too', js: `window.mapViewer.setView('equal_earth'); await new Promise(r => setTimeout(r, 500)); return window.mapViewer.view.shade.mix2.value;`,
+ expect: v => Math.abs(v - 0.4) < 1e-6 },
+ { name: 'over = none hides the slider', js: set('over', '') + `return [document.getElementById('opacity').hidden, window.mapViewer.view.shade.mix2.value];`,
+ expect: ([h, m]) => h === true && m === 0 },
+];