feat(view): show the 3D model on the 형상계획 and 철근배근 screens

The 3D viewer (views, canvas, part toggles) moves into a slot at the top of ②
and ③ while those screens are shown, and back to ① otherwise. Moving the
element keeps the WebGL context; the viewer is measured after its screen is
visible.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-22 12:28:02 +09:00
1 parent e7f57f0a8a
commit 8c96ab76f5
3 files changed
+30 -1

No files matched your search

+23
View File
@@ -678,11 +678,33 @@ function renderShapeOptions(member: MemberId): void {
}
// --- ② 형상계획 (plan.md C1) -------------------------------------------------------------
/**
* The 3D viewer block (views, canvas, part toggles) is shared: it sits in ① and moves into the top slot of
* ② or ③ while that screen is shown. Moving the element keeps the WebGL context.
*/
const viewerHome: { parent: Node | null; next: Node | null } = { parent: null, next: null };
function captureViewerHome(): void {
const block = $<HTMLElement>('viewer-block');
viewerHome.parent = block.parentElement;
viewerHome.next = block.nextElementSibling;
}
function placeViewer(stage: 'shape' | 'plan' | 'rebar'): void {
const block = $<HTMLElement>('viewer-block');
const slot = stage === 'plan' ? $<HTMLElement>('slot-plan') : stage === 'rebar' ? $<HTMLElement>('slot-rebar') : null;
if (slot) slot.appendChild(block);
else if (viewerHome.parent) viewerHome.parent.insertBefore(block, viewerHome.next);
resize();
}
function setStage(stage: 'shape' | 'plan' | 'rebar'): void {
state.stage = stage;
$<HTMLElement>('view-shape').hidden = stage !== 'shape';
$<HTMLElement>('view-plan').hidden = stage !== 'plan';
$<HTMLElement>('view-rebar').hidden = stage !== 'rebar';
// Move the viewer after its new parent is visible, so that resize() measures the real size.
placeViewer(stage);
// The highlight is the 'current' class (style.css); aria-current is set alongside it for assistive tech.
const nav: [string, 'shape' | 'plan' | 'rebar'][] = [['nav-shape', 'shape'], ['nav-plan', 'plan'], ['nav-rebar', 'rebar']];
for (const [id, key] of nav) {
@@ -1378,6 +1400,7 @@ $<HTMLButtonElement>('discard-backup').addEventListener('click', () => {
});
// --- start ------------------------------------------------------------------------------
captureViewerHome();
buildPartToggles();
buildViewButtons();
renderDefaults();
+4
View File
@@ -687,3 +687,7 @@ body { background: #eef1f4; font-family: 'Noto Sans KR', system-ui, sans-serif;
.rebar-table th:nth-child(9),
.rebar-table th:nth-child(10) { text-align: right; }
.rebar-table td:nth-child(12) { white-space: normal; min-width: 240px; }
/* 3D viewer shared by ①, ②, ③: the slot takes the full width above the other columns */
.viewer-slot { flex: 1 1 100%; min-width: 0; }
.viewer-slot > .viewer { width: 100%; }