feat(지도): 634-2 · 634-3 아이콘 표 두 장 · 묶음 메뉴 · 한 행 배선 · 호버 = 표(요구 546)
- 겹 표(map_layer_list) = 그룹1 22 줄 표 차례 · title = 호버제목 · group(수계망도 · 도로 · 토지·건물 · 제한·재해) · pages · 숨김 표 걷음 · 도로300m 한 줄(「도로」 묶음 · 기능 남김) - 겹 줄(map_layer_bar) = 단독 넷 | 묶음 넷(여럿 고르기 메뉴 · 켠 수 배지 · 안 닫힘) | 그래픽 카드 · sync 가 단추 · 메뉴 줄 막힘 · 글을 맞춤(why = 페이지 까닭) - 도구 표(map_toolbar) = 그룹2 17 줄 title · mapToolGroups 가 글을 표로 맞춤 · 기본 단추 생성 · 지형 칩 막힘 「수치지형도/라이다 — 까닭」 - 띠 = 한 자료 · 겹 둘(GL fillEdge 거름 · 옛 캔버스 · 범례 줄 따로) · B05 띠 받기(D03 과 같은 서버 길 · bandCollection 공용) - D03 = 겹 줄 · 도구줄 한 행(createMapToolRow) · 222px 기댐 · 줄바꿈 CSS 걷음 · 측점 · 기울기 호버 덮어쓰기 걷음 · LAS 올리기 호버 걷음 - B05 = 세로 두 줄 → 한 행 · 호버 덮어쓰기 걷음(도구줄 · 1m 등고선 · 3D · 추천) · 겹 막힘 querySelector 덮어쓰기 → 공용 sync · 임도(업로드) 보임 + 「받은 임도 자료 없음」 막힘 · 스냅 간격 날 select → 고르기 메뉴(하나) - 켬끔 기억 열쇠 · 측점 · 기울기 처음 값 · 그래픽 카드 취향 열쇠 둘 그대로 - 낡은 시험 고침(568_1 · 622_2 · 624_2 · 624_3 · 553_4 · 625_draw · b05_routeedit_initial · 626_3 · 390_4 · 346_2 · 353_1 · 581_2 · 584_1 · 584_3) — 표 꼴 row() · 호버 글 = 표 · 한 행 · 고르기 메뉴로 바뀐 글을 잡음 · 새 지킴 634_2 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,27 +1,33 @@
|
||||
/* =============================================================================
|
||||
* map_layer_bar.ts
|
||||
* 공용 지도 겹 줄(PLAN 569-2 · 586-2 · 624-2 · 요구 530) — 겹 단추 한 줄(공용 지도 도구줄 `createMapTools` · 묶음 사이 나눔선) +
|
||||
* 끝에 그래픽 카드 단추(GL ↔ 옛 캔버스).
|
||||
* 보일 겹 · 처음 켬 · 취향 열쇠 = 페이지 표(`map_layer_list` `MAP_LAYER_PAGES`) · 누르면 켬끔 뒤집고 취향에 적고 `onToggle`.
|
||||
* 막힘 = 지형을 아직 안 받음(`sync({ ready: false })`) · 조각만 쓰는 겹은 옛 캔버스에서 「안 보임」 글.
|
||||
* 공용 지도 겹 줄(PLAN 569-2 · 586-2 · 624-2 · 634-2 · 요구 530 · 546) — 겹 단추 한 줄(공용 지도 도구줄 `createMapTools`):
|
||||
* 단독 단추(표 묶음 없음) | 묶음 단추(여럿 고르기 메뉴 · 켠 수 배지 · 골라도 안 닫힘) | 그래픽 카드 단추(GL ↔ 옛 캔버스).
|
||||
* 보일 겹 · 묶음 · 호버제목 · 처음 켬 · 취향 열쇠 = 표(`map_layer_list`) · 누르면 켬끔 뒤집고 취향에 적고 `onToggle`.
|
||||
* 막힘 = 지형을 아직 안 받음(`ready: false`) · 조각만 쓰는 겹은 옛 캔버스에서 · 페이지 까닭(`why`) — 「제목 — 까닭」.
|
||||
* 받기 · 그리기 · 범례는 페이지 몫 — 켬끔 값(`on`)은 같은 객체를 같이 씀.
|
||||
* 쓰는 법 = `createMapLayerBar({ page: "d03", glOn, onToggle, onGl })` → `{ root, bar, on, toggle, save, sync }`.
|
||||
* ========================================================================== */
|
||||
|
||||
import { createIconButton } from "@ui/ui_template_button";
|
||||
import { createMapTools } from "@ui/ui_template_map_tools";
|
||||
import { createPickMenu, type PickMenu } from "@ui/ui_template_context_menu";
|
||||
import { createMapTools, mapToolTip } from "@ui/ui_template_map_tools";
|
||||
import { writeByKey } from "../b_page_state";
|
||||
import { tileOnly } from "./map_forest_layers";
|
||||
import {
|
||||
LAYER_GROUPS,
|
||||
MAP_LAYER_PAGES,
|
||||
pageGroups,
|
||||
pageLayers,
|
||||
readLayerPref,
|
||||
type LayerGroup,
|
||||
type MapLayerKey,
|
||||
type MapPage,
|
||||
} from "./map_layer_list";
|
||||
|
||||
/** 그래픽 카드 단추 호버(표 밖 · 그룹1 끝 단독). */
|
||||
const GL_TITLE = "그래픽 카드";
|
||||
|
||||
export interface MapLayerBar {
|
||||
/** 도구줄 감싼 것(자리는 페이지 CSS). */
|
||||
/** 도구줄 감싼 것(자리는 페이지 CSS · 한 행 = `createMapToolRow`). */
|
||||
root: HTMLElement;
|
||||
/** 도구줄 자체(폭 재기). */
|
||||
bar: HTMLElement;
|
||||
@@ -30,8 +36,12 @@ export interface MapLayerBar {
|
||||
/** 뒤집고 적고 `onToggle`. */
|
||||
toggle: (key: MapLayerKey) => void;
|
||||
save: () => void;
|
||||
/** 단추 눌림 · 막힘 · 글을 켬끔 값에 맞춤. */
|
||||
sync: (state: { ready: boolean; glOn: boolean }) => void;
|
||||
/** 단추 · 메뉴 줄의 눌림 · 막힘 · 글을 켬끔 값에 맞춤 · `why` = 페이지 막힘 까닭(겹마다). */
|
||||
sync: (state: {
|
||||
ready: boolean;
|
||||
glOn: boolean;
|
||||
why?: Partial<Record<MapLayerKey, string>>;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
export function createMapLayerBar(opts: {
|
||||
@@ -49,10 +59,12 @@ export function createMapLayerBar(opts: {
|
||||
save();
|
||||
opts.onToggle(key);
|
||||
};
|
||||
const defs = pageGroups(page);
|
||||
const defs = pageLayers(page);
|
||||
const buttons = new Map<MapLayerKey, HTMLButtonElement>();
|
||||
const groups = defs.map((group) =>
|
||||
group.map((def) => {
|
||||
const menus = new Map<LayerGroup, PickMenu>();
|
||||
const singles: HTMLElement[] = [];
|
||||
for (const def of defs) {
|
||||
if (!def.group) {
|
||||
const button = createIconButton({
|
||||
icon: def.icon,
|
||||
title: def.title,
|
||||
@@ -61,33 +73,58 @@ export function createMapLayerBar(opts: {
|
||||
onClick: () => toggle(def.key),
|
||||
});
|
||||
button.dataset.layer = def.key;
|
||||
button.dataset.tip = def.title;
|
||||
buttons.set(def.key, button);
|
||||
return button;
|
||||
}),
|
||||
);
|
||||
singles.push(button);
|
||||
continue;
|
||||
}
|
||||
if (menus.has(def.group)) continue;
|
||||
const group = def.group;
|
||||
const menu = createPickMenu({
|
||||
multi: true,
|
||||
icon: LAYER_GROUPS[group].icon,
|
||||
title: LAYER_GROUPS[group].name,
|
||||
items: defs
|
||||
.filter((one) => one.group === group)
|
||||
.map((one) => ({ value: one.key, label: one.title, icon: one.icon })),
|
||||
onPick: (key) => key && toggle(key as MapLayerKey),
|
||||
});
|
||||
menu.root.dataset.layerGroup = group;
|
||||
menus.set(group, menu);
|
||||
}
|
||||
for (const def of defs)
|
||||
if (def.group) menus.get(def.group)!.setItem(def.key, { checked: on[def.key] });
|
||||
const glButton = createIconButton({
|
||||
icon: "gauge",
|
||||
title: "그래픽 카드 그림(바탕 겹 · 글을 GPU 로 · 끔 = 옛 캔버스 그림)",
|
||||
title: GL_TITLE,
|
||||
size: 32,
|
||||
pressed: opts.glOn,
|
||||
onClick: opts.onGl,
|
||||
});
|
||||
glButton.dataset.layer = "gl";
|
||||
groups.push([glButton]);
|
||||
const tools = createMapTools({ label: "지도 겹", groups });
|
||||
const tools = createMapTools({
|
||||
label: "지도 겹",
|
||||
groups: [singles, [...menus.values()].map((menu) => menu.root), [glButton]],
|
||||
});
|
||||
|
||||
function sync({ ready, glOn }: { ready: boolean; glOn: boolean }): void {
|
||||
for (const def of defs.flat()) {
|
||||
const button = buttons.get(def.key)!;
|
||||
button.setAttribute("aria-pressed", String(on[def.key]));
|
||||
button.disabled = !ready;
|
||||
const title = !ready
|
||||
? `${def.title} — 지형 받기 뒤 보임`
|
||||
: tileOnly(def.key) && !glOn
|
||||
? `${def.title} — 옛 그림(그래픽 카드 끔)엔 안 보임`
|
||||
: def.title;
|
||||
button.title = title;
|
||||
button.setAttribute("aria-label", title);
|
||||
function sync({ ready, glOn, why = {} }: Parameters<MapLayerBar["sync"]>[0]): void {
|
||||
for (const def of defs) {
|
||||
const reason = !ready
|
||||
? "지형 받기 뒤 보임"
|
||||
: (why[def.key] ??
|
||||
(tileOnly(def.key) && !glOn ? "옛 그림(그래픽 카드 끔)엔 안 보임" : null));
|
||||
const button = buttons.get(def.key);
|
||||
if (button) {
|
||||
button.setAttribute("aria-pressed", String(on[def.key]));
|
||||
button.disabled = !!reason;
|
||||
mapToolTip(button, reason);
|
||||
continue;
|
||||
}
|
||||
menus.get(def.group!)!.setItem(def.key, {
|
||||
checked: on[def.key],
|
||||
disabled: !!reason,
|
||||
title: reason ? `${def.title} — ${reason}` : def.title,
|
||||
});
|
||||
}
|
||||
glButton.setAttribute("aria-pressed", String(glOn));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user