// 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 }, ];