refactor(B04): 전처리 화면 자체 변종을 부품 상자 부품으로 — 켜기 칩 · 분할 고르기 · 고르기 · 슬라이더 · 값 목록 · 카드 · 도구줄 (PLAN 553-1)

- 지도 층 단추 열다섯 안팎 · 표시 토글 셋 · 라이다 겹침 = 켜기 칩(층 색 점) · 도엽 보간 방식 = 분할 고르기 · 도구줄 부품
- 고르기 38 → 고르기 부품 · 점 크기 · 밀도 = 슬라이더 · 입력 파일 정보 = 값 목록 · 초기화 = 위험 고스트 · 묶음 상자 = 카드 + 패널 머리
- 죽은 CSS 열여섯 걷음 · 날 색 → 공통 값 · 가이드 촬영 선택자 · 지킴 시험 test_553_1_pages 늘림

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 22:09:36 +09:00
co-authored by Claude Sonnet 5.5
parent a826804277
commit 58dafb1572
14 changed files with 441 additions and 858 deletions
@@ -9,19 +9,38 @@
* ========================================================================== */
import { createTerrainCompass } from "@ui/ui_template_compass";
import { createButton, createInputField, createSelectField } from "@ui/ui_template_elements";
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { createProgressCircle } from "@ui/ui_template_progress";
import { createToggle } from "@ui/ui_template_toggle";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
}
/** 켜기 칩 부품에 옛 체크 칸 꼴(checked · change)을 입힘 — 뷰어 본체 배선은 그대로. */
function chipCheck(label: string, checked: boolean) {
const toggle = createToggle({ kind: "chip", label, checked, size: 32 });
return {
root: toggle.root,
get checked(): boolean {
return toggle.get();
},
set checked(on: boolean) {
toggle.set(on);
},
// 칩의 자기 클릭 처리가 먼저 서므로 여기서는 이미 바뀐 값을 읽는다.
addEventListener: (_type: "change", listener: () => void) =>
toggle.root.addEventListener("click", listener),
};
}
/** 뷰어 본체가 이어 쓸 엘리먼트 묶음 — 이름은 분리 전 지역변수와 같다. */
export type TerrainViewerChrome = ReturnType<typeof buildTerrainViewerChrome>;
export function buildTerrainViewerChrome() {
const root = document.createElement("div");
root.className = "terrain-model-group";
root.className = "ui-card terrain-model-group";
const statusSpan = document.createElement("span");
statusSpan.className = "terrain-status";
@@ -29,79 +48,57 @@ export function buildTerrainViewerChrome() {
statusSpan.style.color = "var(--color-text-secondary)";
statusSpan.textContent = "모델 선택 대기 중...";
const axesCheck = document.createElement("input");
axesCheck.type = "checkbox";
axesCheck.checked = false;
const axesCheck = chipCheck("축", false);
const rightControls = document.createElement("div");
rightControls.className = "viewer-options model-display-options";
rightControls.className = "model-display-options";
// Surface Toggle
const surfLabel = document.createElement("label");
surfLabel.className = "toggle-label toggle-button";
const surfCheck = document.createElement("input");
surfCheck.type = "checkbox";
surfCheck.checked = true;
surfLabel.append(surfCheck, document.createTextNode(" 서피스"));
const surfCheck = chipCheck("서피스", true);
// 스무딩(tin/dtm 전용) — 지면 필터·서피스와 함께 "지표면 분석" 컨테이너로 옮겼다.
// 주변 입력과 양식을 맞추려고 버튼이 아니라 드롭다운이다(2026-08-01 사용자 지시).
// 상태·재렌더 배선은 여기 그대로 두고, 페이지는 이 엘리먼트를 원하는 자리에 놓기만 한다.
const smoothLabel = document.createElement("label");
smoothLabel.className = "b04-surface__field";
const smoothCaption = document.createElement("span");
smoothCaption.textContent = L("B04_Surface_Field_Smoothing");
const smoothSelect = document.createElement("select");
smoothSelect.className = "b04-surface__select";
(
[
["on", "B04_Surface_Smoothing_On"],
["off", "B04_Surface_Smoothing_Off"],
] as const
).forEach(([value, key]) => {
const option = document.createElement("option");
option.value = value;
option.textContent = L(key);
smoothSelect.append(option);
const smoothField = createSelectField({
label: L("B04_Surface_Field_Smoothing"),
options: [
{ value: "on", text: L("B04_Surface_Smoothing_On") },
{ value: "off", text: L("B04_Surface_Smoothing_Off") },
],
value: "on",
size: 36,
});
smoothSelect.value = "on";
smoothLabel.append(smoothCaption, smoothSelect);
const smoothLabel = smoothField.root;
smoothLabel.classList.add("b04-surface__field");
const smoothSelect = smoothField.select;
// Contour Toggle
const contourLabel = document.createElement("label");
contourLabel.className = "toggle-label toggle-button";
const contourCheck = document.createElement("input");
contourCheck.type = "checkbox";
contourCheck.checked = true;
contourLabel.append(contourCheck, document.createTextNode(" 등고선"));
const contourCheck = chipCheck("등고선", true);
// Contour Interval input form
const intervalForm = document.createElement("form");
intervalForm.className = "contour-interval-form";
const intervalInput = document.createElement("input");
intervalInput.type = "number";
intervalInput.value = "1.0";
const intervalField = createInputField({
type: "number",
value: "1.0",
min: 0.5,
unit: "m",
size: 32,
});
const intervalInput = intervalField.input;
intervalInput.step = "0.5";
intervalInput.min = "0.5";
intervalInput.className = "contour-interval-input";
const intervalSubmit = document.createElement("button");
intervalSubmit.type = "submit";
intervalSubmit.textContent = "적용";
intervalSubmit.className = "contour-interval-submit";
const intervalSubmit = createButton({
label: "적용",
variant: "ghost",
size: 32,
type: "submit",
});
intervalForm.append(
document.createTextNode("간격 "),
intervalInput,
document.createTextNode("m "),
intervalSubmit,
);
intervalForm.append(document.createTextNode("간격 "), intervalField.root, intervalSubmit);
const axesLabel = document.createElement("label");
axesLabel.className = "toggle-label toggle-button";
axesLabel.append(axesCheck, document.createTextNode(" 축"));
rightControls.append(axesLabel, surfLabel, contourLabel, intervalForm);
rightControls.append(axesCheck.root, surfCheck.root, contourCheck.root, intervalForm);
// 표시 토글 묶음 + 상태 줄. 컨테이너(제목)는 페이지가 만든다 — 포인트 옵션과 한 칸을 쓴다.
const optionsContent = document.createElement("div");
@@ -182,18 +179,13 @@ export function buildTerrainViewerChrome() {
root,
statusSpan,
axesCheck,
rightControls,
surfLabel,
surfCheck,
smoothLabel,
smoothCaption,
smoothSelect,
contourLabel,
contourCheck,
intervalForm,
intervalInput,
intervalSubmit,
axesLabel,
optionsContent,
viewerArea,
canvas,