feat(B05/B06): 종단 그래프 줌 버튼 단순화 + 세로 자동 맞춤
- 줌 버튼을 셋(줌인·줌아웃·초기화)으로 줄임. 세로 배율·창 이동 버튼 제거 - 배율 1 = 기본값이자 축소 한계 — 한계에 닿은 버튼은 흐리게 죽임 - 세로는 보이는 누가거리 구간의 지반·계획선 범위로 자동(공통 함수 windowElevationRange, B05·B06 종단이 함께 씀). 스크롤이 멈춘 뒤 0.16초에 갱신 - 계획고 편집 버튼을 누르고 있는 동안 Y 축 고정, 손을 떼면 다시 맞춤 - 유토곡선 Y 도 같은 창 기준(전 구간 ±200㎥ 고정 해제) - B06 종단이 쓰던 공통 Y 스케일(calculateYScale) 제거 — 횡단 카드는 원래 안 쓰던 값 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,12 @@ export interface MassHaulAxis {
|
||||
axisX?: number;
|
||||
/** 그래프 위 여백(px). 생략하면 기본(10). B05는 범례 오버레이만큼 크게 준다. */
|
||||
padTop?: number;
|
||||
/**
|
||||
* **화면에 보이는 누가거리 구간**(m). 넘기면 Y 범위를 이 구간의 누계 토량으로 잡는다
|
||||
* (2026-09-04 사용자 지시 — 종단 그래프의 세로 자동 맞춤과 같은 창). 생략하면 예전처럼
|
||||
* 전 구간 기준 ±200㎥ 고정이다.
|
||||
*/
|
||||
viewRange?: { fromM: number; toM: number };
|
||||
}
|
||||
|
||||
/** 축 눈금이 읽히는 최소 높이. 이보다 낮아지면 그래프가 뭉개진다. */
|
||||
@@ -128,9 +134,44 @@ const VOLUME_RANGE_BASE_M3 = 200;
|
||||
* Y축 상·하한을 잡는다. 기본 −200~+200㎥ 고정(0선 항상 포함), 곡선이 넘치는 쪽만
|
||||
* 데이터에 5% 여유를 더해 확장한다. B05·B06이 같은 함수를 쓰므로 두 화면이 함께 고정된다.
|
||||
*/
|
||||
function volumeRange(series: MassHaulSeries[]): { min: number; max: number } {
|
||||
function volumeRange(
|
||||
series: MassHaulSeries[],
|
||||
viewRange?: { fromM: number; toM: number },
|
||||
): { min: number; max: number } {
|
||||
let rawMin = 0;
|
||||
let rawMax = 0;
|
||||
if (viewRange) {
|
||||
// 보이는 구간만 훑는다. 창 경계를 걸친 선분이 안에서 솟구치므로 바깥 이웃 한 점도 본다.
|
||||
let found = false;
|
||||
for (const entry of series) {
|
||||
const points = entry.result.points;
|
||||
let first = -1;
|
||||
let last = -1;
|
||||
for (let index = 0; index < points.length; index += 1) {
|
||||
const chainage = points[index].chainage_m;
|
||||
if (chainage < viewRange.fromM || chainage > viewRange.toM) continue;
|
||||
if (first < 0) first = index;
|
||||
last = index;
|
||||
}
|
||||
if (first < 0) continue;
|
||||
for (
|
||||
let index = Math.max(0, first - 1);
|
||||
index <= Math.min(points.length - 1, last + 1);
|
||||
index += 1
|
||||
) {
|
||||
const volume = points[index].cumulative_volume_m3;
|
||||
if (!Number.isFinite(volume)) continue;
|
||||
rawMin = found ? Math.min(rawMin, volume) : volume;
|
||||
rawMax = found ? Math.max(rawMax, volume) : volume;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
// 창 안이 거의 평평하면(구간 토량 변화가 없으면) 최소 폭을 줘 선이 축에 붙지 않게 한다.
|
||||
const padding = Math.max((rawMax - rawMin) * 0.05, 1);
|
||||
return { min: rawMin - padding, max: rawMax + padding };
|
||||
}
|
||||
}
|
||||
for (const entry of series) {
|
||||
rawMin = Math.min(rawMin, entry.result.min_cumulative_m3);
|
||||
rawMax = Math.max(rawMax, entry.result.max_cumulative_m3);
|
||||
@@ -323,7 +364,7 @@ export function createMassHaulChart(
|
||||
// 기준 버튼이 라디오가 되면서(택1 표시) Y 범위도 **표시 중인 곡선**으로 잡는다 —
|
||||
// 숨은 기준까지 합쳐 잡으면 선택한 그래프가 눌려 보인다. 아무것도 안 켰으면 전체로 폴백.
|
||||
const rangeSource = series.filter((entry) => visibleKeys.has(entry.key));
|
||||
const { min, max } = volumeRange(rangeSource.length ? rangeSource : series);
|
||||
const { min, max } = volumeRange(rangeSource.length ? rangeSource : series, axis.viewRange);
|
||||
const span = Math.max(max - min, 1e-6);
|
||||
const y = (volume: number) => padTop + ((max - volume) / span) * plotHeight;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user