fix(B06): 횡단면도 Y축 눈금도 정수·1·2·5 계열로 정의
- 5등분 고정(소수 표기) → 종단면도와 같은 niceTickStep 규칙 적용. - niceTickStep을 _UI_Section_Common으로 옮겨 종·횡단이 공유(정의 한 곳). - 횡단은 카드 높이가 낮아 라벨 간격 하한 14px(종단 16px)로 개수 상한 산정. - 횡단 표고 여유는 기존 crossPlotMetrics의 8% 패딩 그대로. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -165,3 +165,27 @@ export function emptyView(message: string): HTMLElement {
|
||||
empty.textContent = message;
|
||||
return empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* 눈금 간격을 1·2·5 ×10^n 중에서 고른다 — 눈금값이 딱 떨어지면서 눈금 개수가
|
||||
* 목표(10칸)에 가장 가까운 것. 다만 라벨이 겹치지 않게 최대 개수(maxCount)를 넘지 않는다.
|
||||
*/
|
||||
export function niceTickStep(span: number, targetCount: number, maxCount: number): number {
|
||||
if (!(span > 0)) return 1;
|
||||
const exponent = Math.floor(Math.log10(span / targetCount));
|
||||
let best = Math.pow(10, exponent + 2);
|
||||
let bestError = Infinity;
|
||||
for (const power of [exponent - 1, exponent, exponent + 1, exponent + 2]) {
|
||||
for (const mantissa of [1, 2, 5]) {
|
||||
const step = mantissa * Math.pow(10, power);
|
||||
const count = Math.floor(span / step) + 1;
|
||||
if (count > Math.max(2, maxCount)) continue;
|
||||
const error = Math.abs(count - targetCount);
|
||||
if (error < bestError) {
|
||||
bestError = error;
|
||||
best = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user