by adom
0402 SMD Red LED · 2.1 V drop · 25 mA max
← Commit history
Embedded viewer UX: close the Layers menu on any click outside it, and make the Bottom-light button work (the shipped bundle has no setBottomLight, so add our own bottom-fill hemispheric light toggled by the button).
1 file changed
+23−1
IN-S42ATR-viewer.html+23−1@@ -107,6 +107,20 @@ const ptLight = scene.lights.find(l => l.getClassName && l.getClassName() === 'PointLight'); const modelParent = (led && led.parent) || null; // share the model's coordinate space + // Bottom-fill light: the shipped bundle exposes no setBottomLight() and builds no bottomLight,+ // so create our own (matching his design — a downward hemispheric that lights the part's+ // underside), using his Babylon instance via the existing hemi's constructor. Toggled by the button.+ let bottomFill = scene.getLightByName('bottomLight');+ if (!bottomFill) {+ const hemi = scene.getLightByName('light') || scene.lights.find(l => l.getClassName && l.getClassName() === 'HemisphericLight');+ if (hemi) {+ const HL = hemi.constructor;+ bottomFill = new HL('our_bottom_fill', new B.Vector3(0,0,-1), scene);+ bottomFill.diffuse = new B.Color3(1,1,1); bottomFill.groundColor = new B.Color3(0.5,0.5,0.5);+ bottomFill.intensity = 0;+ }+ }+ // Replicate his loadModel shadow step (ThreeDViewer.svelte ~159-166): register the loaded // model as shadow casters/receivers. (His current source does this; the shipped bundle is // older, so we do it here — same effect, no change to his code.) refreshRate=1 keeps the@@ -252,9 +266,17 @@ document.getElementById('mode-static').onclick = () => setMode('static'); document.getElementById('mode-pnp').onclick = () => setMode('pnp'); document.getElementById('btn-ground').onclick = function(){ this.classList.toggle('on'); viewer.setGroundVisible(this.classList.contains('on')); };- document.getElementById('btn-bottom').onclick = function(){ this.classList.toggle('on'); viewer.setBottomLight(this.classList.contains('on')); };+ document.getElementById('btn-bottom').onclick = function(){ this.classList.toggle('on'); if (bottomFill) bottomFill.intensity = this.classList.contains('on') ? 0.6 : 0; }; document.getElementById('btn-layers').onclick = function(){ document.getElementById('layer-menu').classList.toggle('open'); this.classList.toggle('on'); }; + // Close the Layers menu on any click outside it (and outside the Layers button).+ document.addEventListener('click', (e) => {+ const menu = document.getElementById('layer-menu'), btn = document.getElementById('btn-layers');+ if (menu.classList.contains('open') && !menu.contains(e.target) && !btn.contains(e.target)) {+ menu.classList.remove('open'); btn.classList.remove('on');+ }+ }, true);+ setMode('static'); window._v = { viewer, scene, B, setMode }; // debug hook } catch (e) { statusEl.textContent = 'init error: ' + e.message; window._err = (e.stack || e.message); console.error(e); }