fix: harden array builder editing workflows

This commit is contained in:
2026-08-28 23:10:41 +09:00
parent 3714146df9
commit 122b6cf7be
14 changed files with 1148 additions and 165 deletions
+68 -62
View File
@@ -12,6 +12,7 @@
<link rel="stylesheet" href="/apps/array-builder/styles.css" />
</head>
<body>
<a class="skip-link" href="#array-canvas">배열 편집 화면으로 건너뛰기</a>
<div class="app-shell array-builder-shell">
<header class="app-header array-builder-header">
<a class="app-brand" href="/">
@@ -39,6 +40,65 @@
</header>
<main class="array-builder-layout" id="array-builder-layout" data-split-layout>
<section class="array-workspace" id="array-builder-workspace" aria-label="마이크 배열 편집 화면">
<div class="workspace-heading">
<div>
<p class="eyebrow">마이크 배치</p>
<h1>Array 평면 편집</h1>
</div>
<p class="workspace-summary" id="workspace-summary">0.45 × 0.45 m · 12 channels</p>
</div>
<div class="workspace-toolbar" role="toolbar" aria-label="배열 편집 도구">
<div class="toolbar-group" aria-label="편집 도구">
<button class="tool-button is-active" id="select-tool-button" type="button" aria-pressed="true" aria-keyshortcuts="V">선택 <kbd>V</kbd></button>
<button class="tool-button" id="add-tool-button" type="button" aria-pressed="false" aria-keyshortcuts="A">추가 <kbd>A</kbd></button>
</div>
<div class="toolbar-group" aria-label="실행 취소와 다시 실행">
<button class="tool-button" id="undo-button" type="button" aria-keyshortcuts="Control+Z" disabled>실행 취소</button>
<button class="tool-button" id="redo-button" type="button" aria-keyshortcuts="Control+Shift+Z" disabled>다시 실행</button>
</div>
<div class="toolbar-group zoom-tools" aria-label="화면 확대와 맞춤">
<button class="icon-button" id="zoom-out-button" type="button" aria-label="축소" title="축소">−</button>
<button class="tool-button" id="fit-view-button" type="button">화면 맞춤</button>
<button class="icon-button" id="zoom-in-button" type="button" aria-label="확대" title="확대">+</button>
</div>
<div class="snap-controls">
<label class="check-field"><input id="snap-enabled" type="checkbox" checked /><span>격자 스냅</span></label>
<label class="compact-field"><span>간격</span><input id="snap-step" type="number" min="0.1" max="1000" step="0.1" value="5" inputmode="decimal" /><small>mm</small></label>
</div>
</div>
<div class="array-canvas-card">
<canvas
id="array-canvas"
tabindex="0"
aria-label="마이크 어레이 평면 편집 canvas"
aria-describedby="canvas-instructions"
></canvas>
<div class="canvas-instructions" id="canvas-instructions">
<strong>마이크를 클릭하거나 드래그해 위치를 편집하세요.</strong>
<span>추가 도구에서는 빈 공간을 클릭해 새 채널을 만듭니다.</span>
</div>
<div class="selection-status" id="selection-status" role="status" aria-live="polite">선택된 마이크 없음</div>
</div>
<section class="array-statistics" aria-label="배열 요약">
<article class="metric-card"><span>채널</span><strong id="microphone-count">12</strong><small>microphones</small></article>
<article class="metric-card"><span>최소 간격</span><strong id="minimum-spacing">—</strong><small>nearest pair</small></article>
<article class="metric-card"><span>무게중심</span><strong id="array-centroid">—</strong><small>x, y, z</small></article>
<article class="metric-card"><span>보정 채널</span><strong id="calibration-count">0</strong><small>sensitivity / phase / response</small></article>
</section>
<details class="shortcut-help">
<summary>빠른 편집 키</summary>
<div>
<p><kbd>V</kbd> 선택 · <kbd>A</kbd> 추가 · <kbd>Delete</kbd> 선택 삭제</p>
<p><kbd>← ↑ ↓ →</kbd> 위치 미세 조정 · <kbd>Shift</kbd>를 함께 누르면 10배 이동</p>
</div>
</details>
</section>
<aside
class="array-controls"
id="array-builder-controls"
@@ -58,7 +118,7 @@
</div>
</section>
<section class="control-section">
<section class="control-section array-metadata-section">
<div class="section-title"><span>01</span><h2>배열 정보</h2></div>
<label class="field field--wide">
<span>이름</span>
@@ -81,7 +141,7 @@
</label>
</section>
<section class="control-section control-section--primary">
<section class="control-section control-section--primary aperture-section">
<div class="section-title"><span>02</span><h2>크기와 형상</h2></div>
<div class="field-grid">
<label class="field">
@@ -100,7 +160,7 @@
<option value="ellipse">타원</option>
</select>
</label>
<p class="section-note">크기를 바꿔도 기존 마이크 좌표는 자동으로 늘어나거나 줄어들지 않습니다.</p>
<p class="section-note">크기를 바꿔도 기존 좌표는 자동으로 늘어나거나 줄어들지 않습니다. 생성 경계 형상은 편집용이며 JSON에는 최종 좌표와 너비·높이만 저장됩니다.</p>
<div class="button-grid button-grid--two">
<button class="button button--ghost" id="center-microphones-button" type="button">좌표 중앙 정렬</button>
<button class="button button--ghost" id="fit-aperture-button" type="button">좌표에 크기 맞춤</button>
@@ -108,7 +168,7 @@
</div>
</section>
<section class="control-section">
<section class="control-section preset-section">
<div class="section-title"><span>03</span><h2>프리셋 생성</h2></div>
<label class="field field--wide">
<span>배치 방식</span>
@@ -201,6 +261,10 @@
</div>
</div>
</section>
<div class="mobile-save-actions">
<button class="button button--primary button--full" id="mobile-export-button" type="button">Array JSON 저장</button>
</div>
</aside>
<div
@@ -216,64 +280,6 @@
title="드래그하거나 방향키로 너비 조절 · Enter/더블클릭으로 초기화"
></div>
<section class="array-workspace" id="array-builder-workspace" aria-label="마이크 배열 편집 화면">
<div class="workspace-heading">
<div>
<p class="eyebrow">마이크 배치</p>
<h1>Array 평면 편집</h1>
</div>
<p class="workspace-summary" id="workspace-summary">0.45 × 0.45 m · 12 channels</p>
</div>
<div class="workspace-toolbar" role="toolbar" aria-label="배열 편집 도구">
<div class="toolbar-group" aria-label="편집 도구">
<button class="tool-button is-active" id="select-tool-button" type="button" aria-pressed="true" aria-keyshortcuts="V">선택 <kbd>V</kbd></button>
<button class="tool-button" id="add-tool-button" type="button" aria-pressed="false" aria-keyshortcuts="A">추가 <kbd>A</kbd></button>
</div>
<div class="toolbar-group" aria-label="실행 취소와 다시 실행">
<button class="tool-button" id="undo-button" type="button" aria-keyshortcuts="Control+Z" disabled>실행 취소</button>
<button class="tool-button" id="redo-button" type="button" aria-keyshortcuts="Control+Shift+Z" disabled>다시 실행</button>
</div>
<div class="toolbar-group zoom-tools" aria-label="화면 확대와 맞춤">
<button class="icon-button" id="zoom-out-button" type="button" aria-label="축소" title="축소">−</button>
<button class="tool-button" id="fit-view-button" type="button">화면 맞춤</button>
<button class="icon-button" id="zoom-in-button" type="button" aria-label="확대" title="확대">+</button>
</div>
<div class="snap-controls">
<label class="check-field"><input id="snap-enabled" type="checkbox" checked /><span>격자 스냅</span></label>
<label class="compact-field"><span>간격</span><input id="snap-step" type="number" min="0.1" max="1000" step="0.1" value="5" inputmode="decimal" /><small>mm</small></label>
</div>
</div>
<div class="array-canvas-card">
<canvas
id="array-canvas"
tabindex="0"
aria-label="마이크 어레이 평면 편집 canvas"
aria-describedby="canvas-instructions"
></canvas>
<div class="canvas-instructions" id="canvas-instructions">
<strong>마이크를 클릭하거나 드래그해 위치를 편집하세요.</strong>
<span>추가 도구에서는 빈 공간을 클릭해 새 채널을 만듭니다.</span>
</div>
<div class="selection-status" id="selection-status" role="status" aria-live="polite">선택된 마이크 없음</div>
</div>
<section class="array-statistics" aria-label="배열 요약">
<article class="metric-card"><span>채널</span><strong id="microphone-count">12</strong><small>microphones</small></article>
<article class="metric-card"><span>최소 간격</span><strong id="minimum-spacing">—</strong><small>nearest pair</small></article>
<article class="metric-card"><span>무게중심</span><strong id="array-centroid">—</strong><small>x, y, z</small></article>
<article class="metric-card"><span>보정 채널</span><strong id="calibration-count">0</strong><small>sensitivity / phase / response</small></article>
</section>
<details class="shortcut-help">
<summary>빠른 편집 키</summary>
<div>
<p><kbd>V</kbd> 선택 · <kbd>A</kbd> 추가 · <kbd>Delete</kbd> 선택 삭제</p>
<p><kbd>← ↑ ↓ →</kbd> 위치 미세 조정 · <kbd>Shift</kbd>를 함께 누르면 10배 이동</p>
</div>
</details>
</section>
</main>
</div>