← back to Dw Catalog 3d
D3: deep-link hash routing (#v=slug, #v=slug&c=i) — replaceState on every transition + restore on load
3448a2321fe74b41d0d5eb5fd7ae7b6492fedd42 · 2026-06-26 10:10:08 -0700 · Steve Studio
Files touched
Diff
commit 3448a2321fe74b41d0d5eb5fd7ae7b6492fedd42
Author: Steve Studio <steve@designerwallcoverings.com>
Date: Fri Jun 26 10:10:08 2026 -0700
D3: deep-link hash routing (#v=slug, #v=slug&c=i) — replaceState on every transition + restore on load
---
public/index.html | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/public/index.html b/public/index.html
index 6baaf07..a97b59b 100644
--- a/public/index.html
+++ b/public/index.html
@@ -169,7 +169,7 @@ function renderVendors(){
eg.position.copy(m.position); world.add(eg); y+=h+0.04; });
if(match){ const lab=label(d.vendor); lab.position.set(cx,y+1.8,cz); lab.userData={kind:'vendor',d}; world.add(lab); }
});
- flyTo([58,46,74],[0,7,0]);
+ flyTo([58,46,74],[0,7,0]); syncHash();
}
// ===================== LEVEL 1 : COLLECTIONS =====================
@@ -200,7 +200,7 @@ async function drillVendor(d){
new THREE.MeshStandardMaterial({color:0xC8A24B,emissive:0xC8A24B,emissiveIntensity:.25,metalness:.6,roughness:.3}));
ped.position.y=0.7; world.add(ped);
const vlab=label(d.vendor,[16,3.6,1],'#C8A24B'); vlab.position.set(0,3.4,0); world.add(vlab);
- flyTo([0,R*1.5,R*1.9],[0,4,0]);
+ flyTo([0,R*1.5,R*1.9],[0,4,0]); syncHash();
}
// ===================== LEVEL 2 : PRODUCTS =====================
@@ -222,7 +222,7 @@ function drillCollection(cobj){
undefined,()=>{m.material=fallback.clone();}); } else m.material=fallback.clone();
});
const r=Math.max(20,cols*gap*1.1);
- flyTo([0,8,r],[0,8,0]);
+ flyTo([0,8,r],[0,8,0]); syncHash();
}
// ---- legends / breadcrumb ----
@@ -276,6 +276,24 @@ window.__vendor=()=>{ if(state.vData) drillVendor(state.vendor); };
window.__drill=(slug)=>drillVendor(DATA.find(d=>d.slug===slug)||DATA.find(d=>d.slug));
window.__coll=(i)=>{ if(state.vData) drillCollection(state.vData.collections[i||0]); };
+// ---- D3: deep-link hash routing (#v=<slug> | #v=<slug>&c=<i>) ----
+function syncHash(){
+ let h='';
+ if(state.vendor&&state.vendor.slug){ h='v='+encodeURIComponent(state.vendor.slug);
+ if(state.level===2&&state.coll&&state.vData){ const i=state.vData.collections.indexOf(state.coll);
+ if(i>=0) h+='&c='+i; } }
+ const nh=h?'#'+h:location.pathname+location.search; // bare path clears the hash
+ if(location.hash.replace(/^#/,'')!==h) history.replaceState(null,'',nh);
+}
+async function restoreFromHash(rawHash){
+ const m=new URLSearchParams((rawHash||location.hash).replace(/^#/,''));
+ const slug=m.get('v'); if(!slug) return; // nothing to restore → stay at L0
+ const d=DATA.find(x=>x.slug===slug); if(!d) return;
+ await drillVendor(d); // L1 (awaits the v/<slug>.json fetch)
+ const ci=m.get('c');
+ if(ci!=null&&state.vData&&state.vData.collections[+ci]) drillCollection(state.vData.collections[+ci]); // L2
+}
+
// ---- interaction ----
const ray=new THREE.Raycaster(), mouse=new THREE.Vector2(), tip=document.getElementById('tooltip');
let downXY=null;
@@ -342,8 +360,9 @@ sinput.addEventListener('keydown',e=>{
});
document.addEventListener('click',e=>{ if(!document.getElementById('search').contains(e.target)) sresults.style.display='none'; });
+const __initialHash=location.hash; // capture before renderVendors() clears it via syncHash
fetch('scene.json?_='+Date.now()).then(r=>r.json()).then(d=>{
- DATA=d.sort((a,b)=>(b.active+b.archived)-(a.active+a.archived)); renderVendors(); });
+ DATA=d.sort((a,b)=>(b.active+b.archived)-(a.active+a.archived)); renderVendors(); restoreFromHash(__initialHash); });
addEventListener('resize',()=>{camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight);});
(function loop(){requestAnimationFrame(loop);stepFly();controls.update();renderer.render(scene,camera);})();
← 4f30f3d Frontend: L2 Active/Staged/Draft status filter chips + L0 ve
·
back to Dw Catalog 3d
·
D1: document daily refresh (path B — standalone com.steve.ca 320cfff →