main
John Lauer Bundle fan preview data for authenticated wiki rendering without companion fetches e73bd0e 12d ago
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Adom · Fan component states</title><link rel="icon" href="data:,"><link rel="stylesheet" href="https://wiki.adom.inc/static/vendor/adom-3d-viewer-babylon9/style.css"><script type="module" src="https://wiki.adom.inc/static/vendor/adom-3d-viewer-babylon9/adom-3d-viewer-babylon9.esm.js"></script><style>body{margin:0;background:#10161d;color:#e6edf3;font:15px system-ui}header{height:44px;box-sizing:border-box;padding:10px 18px;border-bottom:1px solid #35424c}#view{position:absolute;top:44px;bottom:0;left:320px;right:0}aside{width:280px;padding:20px}h1{font-size:23px}p{color:#aabac6;line-height:1.5}button,input,select{font:inherit}button{background:#253847;color:#fff;border:1px solid #618092;border-radius:6px;padding:9px 20px;margin-right:6px;cursor:pointer}button.active{background:#087c76}input[type=range]{width:100%}strong{font-size:30px;color:#5ee4ce}label{display:block;margin:18px 0}#badge{color:#ffd17b}#status{font-size:12px;white-space:pre-wrap}small{color:#aabac6}</style></head><body><header>Adom / Component states / Sunon fan</header><aside><h1>MF40200V1-1000U-G99</h1><p>Fan state and speed preview</p><div id="badge">SIMULATED · no hardware connection</div><p><strong id="rpm">0</strong> RPM</p><button id="off" class="active">Off</button><button id="on">On</button><label>Simulated rotor speed <input id="speed" type="range" min="0" max="10000" step="100" value="7000"><output id="requested">7000 RPM</output></label><label>Playback<select id="scale"><option value="0.02">Slow motion · 0.02×</option><option value="1">Real time · 1×</option></select></label><p id="rate">Rotor stopped</p><small>Nominal envelope. Blade and support geometry are illustrative. Animation demonstrates state control; it does not prove airflow or cooling.</small><p><small>At high RPM, screen sampling can make blades appear slower or reversed.</small></p><div id="status">Loading canonical Adom viewer…</div></aside><div id="view"></div><script type="module">
import {bindFanMotion} from '../states/controller.js';
const $=id=>document.getElementById(id);let state='off';
try{
const V=window.Adom3DViewerBabylon9,B=window.BABYLON;const v=V.init($('view'),{zUp:true,showViewCube:true,showGround:false});const scene=v.getScene();window.fanViewer=v;scene.lights.filter(l=>l.name==='light').forEach(l=>l.intensity=1.4);
const imported=await B.SceneLoader.ImportMeshAsync('','../states/','fan-animated.glb',scene);imported.meshes[0].scaling.scaleInPlace(1000);const manifest=await(await fetch('../states.json')).json();const motion=bindFanMotion(imported,manifest);window.fanMotion=motion;window.fanImported=imported;window.fanScene=scene;
const c=v.getCamera();c.setTarget(new B.Vector3(0,0,10));c.radius=105;c.alpha=-1.15;c.beta=.70;
function apply(){const speed=state==='off'?0:Number($('speed').value),timeScale=Number($('scale').value);const s=motion.apply({state,speed,timeScale,source:'simulated'});$('rpm').textContent=s.speed;$('requested').textContent=$('speed').value+' RPM';$('rate').textContent=state==='off'?'Rotor stopped':`${timeScale}× playback · ${(speed*timeScale).toFixed(0)} displayed RPM`;$('off').classList.toggle('active',state==='off');$('on').classList.toggle('active',state==='on');$('status').textContent='Rotor: Fan.Rotor\nAnimation: Fan.Rotor.Revolution';return s;}
$('off').onclick=()=>{state='off';apply()};$('on').onclick=()=>{state='on';apply()};$('speed').oninput=apply;$('scale').onchange=apply;
window.fanPreview={set(s,rpm,scale=.02){state=s;$('speed').value=rpm;$('scale').value=scale;return apply()},status:()=>motion.status()};
addEventListener('pagehide',()=>motion.dispose());document.addEventListener('visibilitychange',()=>{if(document.hidden)motion.pause();else apply()});
apply();await new Promise(r=>scene.executeWhenReady(r));v.toggleAxes('world',false);scene.lights.filter(l=>l.name==='light').forEach(l=>l.intensity=1.4);scene.getEngine().hideLoadingUI();window.fanReady=true;
}catch(e){$('status').textContent=e.stack;console.error(e)}
</script></body></html>