fix(B06): 측점 라벨 가운데 정렬, 곡선 토글 오버레이 복귀, 면적표 색 테마화, 재선택 해제
- 측점 라벨을 종단면도 축선과 유토곡선 사이 틈의 가운데로 옮긴다. LONG_PAD.bottom 52 → 26, 측점선 끝 +8 연장 제거, 유토곡선 상단 여백 12 → 10. 틈이 53 → 36px로 좁아진다. 좌우 여백은 X축 정렬 값이라 건드리지 않았다. - 곡선 토글을 별도 행에서 유토곡선 우측 상단 오버레이로 되돌린다. 단 스크롤 컨테이너 밖에서 절대 위치로 띄워 컨테이너 폭 계산에 끼어들지 않게 했다(예전 X축 어긋남의 원인). - 면적표·밴드 색을 고정 RGB에서 테마 토큰으로 교체. 발파암(BR)에 쓰던 검정 계열이 다크 테마에서 배경에 묻혔다. 차트 팔레트는 두 테마 모두에 맞춘 밝기다. - 같은 측점을 다시 고르면 선택을 푼다. 카드와 측점 세로선이 같은 경로를 타므로 한 곳에서 처리. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -274,21 +274,21 @@ export function createLongitudinalProfile(
|
||||
x1: stationX,
|
||||
y1: LONG_PAD.top,
|
||||
x2: stationX,
|
||||
y2: heightPx - LONG_PAD.bottom + 8,
|
||||
y2: heightPx - LONG_PAD.bottom,
|
||||
class: "b06-chart__station-hit",
|
||||
}),
|
||||
svgElement("line", {
|
||||
x1: stationX,
|
||||
y1: LONG_PAD.top,
|
||||
x2: stationX,
|
||||
y2: heightPx - LONG_PAD.bottom + 8,
|
||||
y2: heightPx - LONG_PAD.bottom,
|
||||
class: `b06-chart__station-line b06-chart__station-line--${selected ? "selected" : station.kind}`,
|
||||
}),
|
||||
// 측점 라벨은 그래프 바닥에 붙인다 — 바로 아래 유토곡선과의 틈을 줄여 두 그래프가
|
||||
// 측점 표기를 공유하는 것처럼 보이게 한다(2026-08-02 사용자 지시).
|
||||
// 측점 라벨은 축선과 아래 유토곡선 사이 틈의 **가운데**에 놓는다 — 두 그래프가 측점
|
||||
// 표기를 함께 쓰는 것처럼 보여야 한다(2026-08-02 사용자 지시).
|
||||
svgText(offsetStationLabel(station.chainage_m, stationInterval, stationNumberOffset), {
|
||||
x: stationX,
|
||||
y: heightPx - 7,
|
||||
y: heightPx - 5,
|
||||
"text-anchor": "middle",
|
||||
class: "b06-chart__station-label",
|
||||
}),
|
||||
|
||||
@@ -42,7 +42,7 @@ export const MASS_HAUL_HEIGHT = 190;
|
||||
* 붙여 두 그래프가 측점 표기를 공유하는 것처럼 보이게 하기 위해서다(2026-08-02 사용자 지시).
|
||||
* 아래쪽은 X축 제목을 종단면도 상단으로 합치면서 비었다.
|
||||
*/
|
||||
const MASS_PAD_TOP = 12;
|
||||
const MASS_PAD_TOP = 10;
|
||||
const MASS_PAD_BOTTOM = 16;
|
||||
|
||||
const BASIS_LABEL: Record<MassHaulBasis, LocaleKey> = {
|
||||
|
||||
@@ -27,7 +27,10 @@ export const CROSS_HEIGHT = 250;
|
||||
// 한 행 맞춤 기준 최소 카드 폭 — 조금 더 넓은 화면 필요(480→560, 약 +17%).
|
||||
export const CROSS_GRID_MIN_WIDTH = 560;
|
||||
export const CROSS_GRID_GAP = 16;
|
||||
export const LONG_PAD = { left: 62, right: 24, top: 30, bottom: 52 };
|
||||
// bottom은 측점 라벨 한 줄 몫이다. X축 제목을 그래프 상단으로 올린 뒤 남던 여백을 걷어내,
|
||||
// 종단면도 아래 라벨이 그 밑 유토곡선과의 틈 **가운데**에 오도록 좁혔다(2026-08-02 사용자 지시).
|
||||
// left/right는 유토곡선과 X축을 맞추는 값이라 함부로 바꾸면 두 그래프 측점선이 어긋난다.
|
||||
export const LONG_PAD = { left: 62, right: 24, top: 30, bottom: 26 };
|
||||
export const CROSS_PAD = { left: 58, right: 20, top: 10, bottom: 52 };
|
||||
|
||||
export interface YScaleOptions {
|
||||
|
||||
@@ -59,11 +59,11 @@ import {
|
||||
export type { CrossDesignChange, DesignChangeHandler, RockBoundaryControl };
|
||||
|
||||
/**
|
||||
* 헤더(캐럿 행)·범례줄·요약줄·테두리가 먹는 세로 공간. 패널 높이에서 이만큼 빼야 그래프
|
||||
* 몫이 된다. (`.b06-section__panel-body`가 `overflow: hidden`이라 모자라면 아래가 잘린다.
|
||||
* 범례는 CSS에서 한 줄 고정 가로 스크롤이라 개수가 늘어도 이 값이 흔들리지 않는다.)
|
||||
* 헤더(캐럿 행)·요약줄·테두리가 먹는 세로 공간. 패널 높이에서 이만큼 빼야 그래프 몫이 된다.
|
||||
* (`.b06-section__panel-body`가 `overflow: hidden`이라 모자라면 아래가 잘린다.
|
||||
* 범례는 그래프 위에 겹치는 오버레이라 흐름 높이를 먹지 않는다.)
|
||||
*/
|
||||
const PANEL_CHROME_PX = 130;
|
||||
const PANEL_CHROME_PX = 100;
|
||||
/** 손대지 않았을 때의 패널 높이 — 이 값이 축소 비례의 기준(H₀)이 된다. */
|
||||
const BASE_PANEL_HEIGHT = LONG_HEIGHT + MASS_HAUL_HEIGHT + PANEL_CHROME_PX;
|
||||
const MIN_LONG_HEIGHT = 110;
|
||||
@@ -260,10 +260,12 @@ export function createSectionView(
|
||||
document.getElementById(`cross-${stationId}`)?.scrollIntoView({ behavior, block: "nearest" });
|
||||
};
|
||||
|
||||
/** 같은 측점을 다시 고르면 선택을 푼다(2026-08-02 사용자 지시) — 카드·측점선 어느 쪽이든. */
|
||||
const selectStation = (stationId: string, scroll: boolean): void => {
|
||||
selectedStationId = stationId;
|
||||
const deselect = selectedStationId === stationId;
|
||||
selectedStationId = deselect ? null : stationId;
|
||||
draw();
|
||||
if (scroll) revealCard(stationId, "smooth");
|
||||
if (scroll && !deselect) revealCard(stationId, "smooth");
|
||||
};
|
||||
|
||||
const buildCrossCard = (section: CrossSection, forcedHeightPx?: number): HTMLElement =>
|
||||
@@ -345,8 +347,14 @@ export function createSectionView(
|
||||
|
||||
panel.querySelector(".b06-masshaul__legend")?.remove();
|
||||
panel.querySelector(".b06-masshaul__summary")?.remove();
|
||||
// 범례는 그래프 아래, 스크롤 컨테이너 밖에 둔다(곡선 폭에 관여하지 않게).
|
||||
if (series.length) panelBody.append(createMassHaulLegend(series, visibleSeries, toggleSeries));
|
||||
// 범례는 유토곡선 우측 상단에 겹쳐 놓는다(2026-08-02 사용자 지시). 다만 **스크롤 컨테이너
|
||||
// 밖**에서 절대 위치로 띄운다 — 안에 넣으면 컨테이너 폭 계산에 끼어들어 두 그래프의
|
||||
// 측점 세로선이 어긋난다(1차 수정에서 겪은 문제). 세로 위치는 종단면도 높이로 잡는다.
|
||||
if (series.length) {
|
||||
const legend = createMassHaulLegend(series, visibleSeries, toggleSeries);
|
||||
legend.style.top = `${heights.long + 6}px`;
|
||||
panelBody.append(legend);
|
||||
}
|
||||
// 요약 수치는 켜 둔 곡선 중 첫 번째 것 — 곡선이 여러 개라 어느 것인지 요약 끝에 밝힌다.
|
||||
// (선택 측점의 구간 물량은 곡선 위 말풍선이 맡는다.)
|
||||
const summarySeries = series.find((entry) => visibleSeries.has(entry.key));
|
||||
|
||||
@@ -58,7 +58,9 @@
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
/* position: relative — 유토곡선 범례가 이 상자를 기준으로 우측 상단에 겹친다. */
|
||||
.b06-section__panel-body {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
@@ -554,26 +556,28 @@
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* 면적 표기 색은 **테마 토큰만** 쓴다. 고정 RGB를 박으면 다크 테마에서 글자가 배경에
|
||||
묻힌다(발파암에 쓰던 검정이 그랬다). 차트 팔레트는 밝기가 두 테마 모두에 맞춰져 있다. */
|
||||
.b06-design__area--cut,
|
||||
.b06-design__area--cut_total {
|
||||
color: rgb(220 38 38);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
/* 절토 내역 — 토사(EA), 리핑암(RR), 발파암(BR)을 색으로 갈라 둔다. */
|
||||
.b06-design__area--cut_soil {
|
||||
color: rgb(217 119 6);
|
||||
color: var(--color-chart-2);
|
||||
}
|
||||
|
||||
.b06-design__area--cut_rr {
|
||||
color: rgb(71 85 105);
|
||||
color: var(--color-slate);
|
||||
}
|
||||
|
||||
.b06-design__area--cut_br {
|
||||
color: rgb(15 23 42);
|
||||
color: var(--color-chart-3);
|
||||
}
|
||||
|
||||
.b06-design__area--fill {
|
||||
color: rgb(37 99 235);
|
||||
color: var(--color-chart-0);
|
||||
}
|
||||
|
||||
.b06-design__area--unset {
|
||||
@@ -607,21 +611,22 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 밴드 색은 위 면적표 글자색과 짝을 맞춘다 — 어느 숫자를 켰는지 색으로 바로 읽히게. */
|
||||
.b06-chart__area--cut_soil.is-active > polygon {
|
||||
fill: color-mix(in srgb, rgb(217 119 6) 28%, transparent);
|
||||
stroke: rgb(217 119 6);
|
||||
fill: color-mix(in srgb, var(--color-chart-2) 28%, transparent);
|
||||
stroke: var(--color-chart-2);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
.b06-chart__area--cut_rock.is-active > polygon {
|
||||
fill: color-mix(in srgb, rgb(71 85 105) 28%, transparent);
|
||||
stroke: rgb(71 85 105);
|
||||
fill: color-mix(in srgb, var(--color-slate) 28%, transparent);
|
||||
stroke: var(--color-slate);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
.b06-chart__area--fill.is-active > polygon {
|
||||
fill: color-mix(in srgb, rgb(37 99 235) 28%, transparent);
|
||||
stroke: rgb(37 99 235);
|
||||
fill: color-mix(in srgb, var(--color-chart-0) 28%, transparent);
|
||||
stroke: var(--color-chart-0);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,17 @@
|
||||
* 색상은 theme.css 변수만 쓴다. 횡단 기준의 보라는 참고 도면의 자주색에 대응한다.
|
||||
* ========================================================================== */
|
||||
|
||||
/* 범례는 그래프 **아래**, 가로 스크롤 컨테이너 밖에 놓인다(곡선 폭 계산에 끼어들면 종단면도와
|
||||
측점 세로선이 어긋난다). 개수가 늘어도 패널 높이 배분이 흔들리지 않도록 한 줄로 고정하고,
|
||||
넘치면 줄바꿈 대신 이 줄만 가로로 민다. */
|
||||
/* 범례는 유토곡선 **우측 상단에 겹친다**. 단 가로 스크롤 컨테이너 **밖**에서 절대 위치로
|
||||
띄운다 — 안에 넣으면 컨테이너 폭 계산에 끼어들어 종단면도와 측점 세로선이 어긋난다.
|
||||
세로 위치(top)는 종단면도 높이에 맞춰 렌더러가 인라인으로 넣는다. */
|
||||
.b06-masshaul__legend {
|
||||
position: absolute;
|
||||
right: var(--spacing-8);
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: var(--spacing-8);
|
||||
padding: var(--spacing-4) var(--spacing-16);
|
||||
overflow-x: auto;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
.b06-masshaul__legend-item {
|
||||
|
||||
Reference in New Issue
Block a user