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:
@@ -1,9 +1,13 @@
|
||||
import { RENDER_OPTIONS } from "@config/config_frontend";
|
||||
import { createBadge } from "@ui/ui_template_badge";
|
||||
import { createButton } from "@ui/ui_template_elements";
|
||||
import { createSlider } from "@ui/ui_template_input";
|
||||
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
|
||||
import { createProgressCircle } from "@ui/ui_template_progress";
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import type { SurfaceBounds, SurfacePointCloudSampleResponse } from "./B04_PreProcess_Api_Fetch";
|
||||
import { buildSurfaceGroup } from "./B04_PreProcess_UI_Group";
|
||||
import {
|
||||
bindCursorPivotControls,
|
||||
bindSurfaceViewerTheme,
|
||||
@@ -41,19 +45,16 @@ export interface SurfacePointCloudViewer {
|
||||
type CameraView = "iso" | "top" | "front" | "side";
|
||||
|
||||
function makeButton(label: string): HTMLButtonElement {
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.textContent = label;
|
||||
return button;
|
||||
return createButton({ label, variant: "ghost", size: 28 });
|
||||
}
|
||||
|
||||
export function createSurfacePointCloudViewer(): SurfacePointCloudViewer {
|
||||
const root = document.createElement("div");
|
||||
root.className = "point-viewer";
|
||||
root.className = "ui-card point-viewer";
|
||||
|
||||
const statusSpan = document.createElement("span");
|
||||
statusSpan.className = "b04-surface__status-info";
|
||||
statusSpan.textContent = "포인트 데이터 로딩 중...";
|
||||
// 뷰어 위 상태 글 — 배지 부품 · 자리(좌상단)만 B04 쪽 클래스가 정함
|
||||
const statusSpan = createBadge("포인트 데이터 로딩 중...", "neutral");
|
||||
statusSpan.classList.add("b04-surface__status-info");
|
||||
|
||||
const controls = document.createElement("div");
|
||||
controls.className = "viewer-controls";
|
||||
@@ -65,60 +66,31 @@ export function createSurfacePointCloudViewer(): SurfacePointCloudViewer {
|
||||
];
|
||||
controls.append(...viewButtons.map(([, button]) => button));
|
||||
|
||||
const controlsGroup = document.createElement("section");
|
||||
controlsGroup.className = "b04-surface__group";
|
||||
const controlsTitle = document.createElement("h3");
|
||||
controlsTitle.className = "b04-surface__panel-title";
|
||||
controlsTitle.textContent = L("B04_Surface_Group_ViewControls");
|
||||
controlsGroup.append(controlsTitle, controls);
|
||||
|
||||
/** 슬라이더 한 줄 — `이름 [현재값] [게이지]`. 값이 게이지 앞에 온다(2026-08-01 사용자 지시). */
|
||||
function buildSlider(
|
||||
label: string,
|
||||
attributes: { min: string; max: string; step: string; value: string },
|
||||
): { root: HTMLLabelElement; input: HTMLInputElement; value: HTMLSpanElement } {
|
||||
const root = document.createElement("label");
|
||||
root.className = "viewer-option-row";
|
||||
const name = document.createElement("span");
|
||||
name.className = "viewer-option-name";
|
||||
name.textContent = label;
|
||||
const value = document.createElement("span");
|
||||
value.className = "viewer-option-val";
|
||||
const input = document.createElement("input");
|
||||
input.type = "range";
|
||||
input.min = attributes.min;
|
||||
input.max = attributes.max;
|
||||
input.step = attributes.step;
|
||||
input.value = attributes.value;
|
||||
root.append(name, value, input);
|
||||
return { root, input, value };
|
||||
}
|
||||
const controlsGroup = buildSurfaceGroup(L("B04_Surface_Group_ViewControls"), [controls]);
|
||||
|
||||
/** 점 크기 · 밀도 — 슬라이더 부품(이름 · 막대 · 현재값). */
|
||||
const options = document.createElement("div");
|
||||
options.className = "viewer-options";
|
||||
const size = buildSlider(L("B04_Surface_Opt_PointSize"), {
|
||||
min: "0.1",
|
||||
max: "2.5",
|
||||
step: "0.01",
|
||||
value: "0.42",
|
||||
options.className = "b04-surface__options";
|
||||
const size = createSlider({
|
||||
label: L("B04_Surface_Opt_PointSize"),
|
||||
min: 0.1,
|
||||
max: 2.5,
|
||||
step: 0.01,
|
||||
value: 0.42,
|
||||
format: (value) => value.toFixed(2),
|
||||
});
|
||||
const density = buildSlider(L("B04_Surface_Opt_Density"), {
|
||||
min: "1",
|
||||
max: "10",
|
||||
step: "1",
|
||||
value: "10",
|
||||
const density = createSlider({
|
||||
label: L("B04_Surface_Opt_Density"),
|
||||
min: 1,
|
||||
max: 10,
|
||||
step: 1,
|
||||
value: 10,
|
||||
format: (value) => `${value * 10}%`,
|
||||
});
|
||||
const sizeInput = size.input;
|
||||
const densityInput = density.input;
|
||||
options.append(size.root, density.root);
|
||||
|
||||
/** 게이지 앞 숫자를 현재값으로 맞춘다. */
|
||||
function syncOptionValues(): void {
|
||||
size.value.textContent = Number(sizeInput.value).toFixed(2);
|
||||
density.value.textContent = `${Number(densityInput.value) * 10}%`;
|
||||
}
|
||||
syncOptionValues();
|
||||
|
||||
const viewerArea = document.createElement("div");
|
||||
viewerArea.className = "three-viewer";
|
||||
const canvas = document.createElement("canvas");
|
||||
@@ -329,12 +301,10 @@ export function createSurfacePointCloudViewer(): SurfacePointCloudViewer {
|
||||
button.addEventListener("click", () => setCameraView(view));
|
||||
});
|
||||
sizeInput.addEventListener("input", () => {
|
||||
syncOptionValues();
|
||||
if (pointsObject)
|
||||
(pointsObject.material as THREE.PointsMaterial).size = Number(sizeInput.value);
|
||||
});
|
||||
densityInput.addEventListener("input", () => {
|
||||
syncOptionValues();
|
||||
if (currentData) renderPointCloud(currentData);
|
||||
});
|
||||
orbit.addEventListener("change", emitCameraState);
|
||||
@@ -366,9 +336,8 @@ export function createSurfacePointCloudViewer(): SurfacePointCloudViewer {
|
||||
},
|
||||
resetOptions() {
|
||||
axes.visible = false;
|
||||
sizeInput.value = "0.42";
|
||||
densityInput.value = "10";
|
||||
syncOptionValues();
|
||||
size.set(0.42);
|
||||
density.set(10);
|
||||
if (currentData) renderPointCloud(currentData);
|
||||
setCameraView("iso");
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user