diff --git a/web/app.js b/web/app.js index b8174e3..b9aaf0e 100644 --- a/web/app.js +++ b/web/app.js @@ -33,6 +33,7 @@ function drawProfile(f){ c.fillStyle='#587455';c.textAlign='left';c.fillText(`관저 ${fmt(z1,3)}`,13,142);c.textAlign='right';c.fillText(`${fmt(z2,3)} m`,227,142); } export function selectFacility(f){ + if(f&&window.innerWidth<=1000)setPanel('inspector',true); if(!f)return;app.selected=f;app.renderer.set({selected:f.pickId});$('#view-name').textContent=f.id; let html=`${labels[f.type]}

${esc(f.id)}

`; const reviewReasons=app.network.issues.filter(i=>['length_mismatch','adverse_slope','missing_coordinate','unplaced_link','coincident_endpoints'].includes(i.code)&&i.ids.includes(f.id)); @@ -87,6 +88,29 @@ function updateScales(){ const height=Number($('#height-scale').value),size=Number($('#size-scale').value);app.renderer.set({height,size,section:$('#section-mode').checked}); $('#height-output').value=`×${height}`;$('#size-output').value=`×${size}`;$('#height-badge').textContent=`높이 ×${height}`;$('#size-badge').textContent=`단면·맨홀 폭 ×${size}`;$('#section-badge').hidden=!$('#section-mode').checked; } +function setPanel(panel,open){ + const narrow=window.innerWidth<=1000; + if(narrow&&open)document.body.classList.add(panel==='controls'?'hide-inspector':'hide-controls'); + document.body.classList.toggle(`hide-${panel}`,!open); + for(const name of ['controls','inspector']){ + const visible=!document.body.classList.contains(`hide-${name}`); + $(`#toggle-${name}`).setAttribute('aria-expanded',String(visible)); + $(`#${name}-panel`).inert=!visible; + } + $('#panel-backdrop').hidden=!narrow||['controls','inspector'].every(n=>document.body.classList.contains(`hide-${n}`)); +} +function initPanels(){ + const narrow=matchMedia('(max-width: 1000px)'); + const layout=()=>{setPanel('controls',!narrow.matches);setPanel('inspector',!narrow.matches);}; + layout();narrow.addEventListener('change',layout); + for(const name of ['controls','inspector'])$(`#toggle-${name}`).onclick=()=>setPanel(name,document.body.classList.contains(`hide-${name}`)); + $('#panel-backdrop').onclick=()=>{setPanel('controls',false);setPanel('inspector',false);}; + document.addEventListener('keydown',e=>{if(e.key==='Escape'&&narrow.matches&&!$('dialog[open]')){ + const wasControls=!document.body.classList.contains('hide-controls'); + setPanel('controls',false);setPanel('inspector',false); + $(`#toggle-${wasControls?'controls':'inspector'}`).focus(); + }}); +} function syncAuditHighlight(){ const enabled=$('#audit-highlight').checked,reduced=matchMedia('(prefers-reduced-motion: reduce)').matches; const steady=$('#audit-steady').checked||reduced; @@ -114,6 +138,7 @@ function updateAudit(){ } function fatal(message){$('#loading').hidden=true;$('#fatal-error').hidden=false;$('#fatal-error').textContent=message;$('#render-status').textContent='실행 확인 필요';} async function main(){ + initPanels(); try{ const response=await fetch('data/network.json',{cache:'no-store'});if(!response.ok)throw Error('관망 데이터를 읽을 수 없습니다. web/data/network.json 파일이 포함되어 있는지 확인해 주세요.'); app.network=await response.json();const n=app.network,s=n.summary;