fix(B05): 계획노선 편집 빈 화면 — 창 크기가 바뀌어도 가운데 · 배율 유지 · 노선 안 보이는 기억은 버림(73-15)
- resize 가 px 이동량을 그대로 두고 지도 틀만 다시 잡아 지도가 밀림 → 밀린 자리가 보던 화면으로 저장돼 다시 열어도 빈 화면 - 63-1 로 편집 창이 화면 크기를 따라가게 되면서 창 크기 변경마다 밀림 - 창을 열 때 기억한 화면에 노선이 한 점도 없으면 노선 전체 맞춤으로 엶(이미 밀려 저장된 값 복구) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
@@ -48,6 +48,7 @@ import {
|
||||
createViewMemory,
|
||||
fitCanvas,
|
||||
openingView,
|
||||
restoreSavedView,
|
||||
screenToMetric,
|
||||
viewPxPerMeter,
|
||||
} from "./B05_Profile_UI_RouteEdit_View";
|
||||
@@ -232,8 +233,12 @@ export async function openRouteEditModal(
|
||||
|
||||
function resize(): void {
|
||||
if (closed) return;
|
||||
// 크기가 바뀌어도 가운데 자리 · 배율을 지킨다 — px 이동량을 그대로 두면 지도가 밀려
|
||||
// 노선이 화면 밖으로 나가고, 그 자리가 보던 화면으로 저장돼 다시 열어도 빈 화면이 된다.
|
||||
const kept = meta && viewReady ? captureView(meta, view, rotation.radians()) : null;
|
||||
const { width, height } = fitCanvas(canvas, context);
|
||||
view = { ...view, width, height, mapRect: computeMapRect(meta, width, height) };
|
||||
if (meta && kept) view = { ...view, ...restoreSavedView(meta, view, kept) };
|
||||
draw();
|
||||
}
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
@@ -108,7 +108,15 @@ export function openingView(
|
||||
const saved = readSavedView(projectId);
|
||||
if (saved) {
|
||||
const rotationRad = (saved.rotationDeg * Math.PI) / 180;
|
||||
return { view: { ...view, ...restoreSavedView(meta, view, saved) }, rotationRad };
|
||||
const restored: ViewState = { ...view, ...restoreSavedView(meta, view, saved) };
|
||||
// 노선이 한 점도 안 보이는 기억(밀려 저장된 화면)은 버린다 — 빈 화면으로 열리지 않게.
|
||||
// 가운데에서 짧은 변 절반 안 — 회전축이 가운데라 돌려도 같은 판정이다.
|
||||
const reach = Math.min(view.width, view.height) / 2;
|
||||
const seen = nodes.some(([x, y]) => {
|
||||
const [px, py] = metricToScreen(meta, restored, x, y);
|
||||
return Math.hypot(px - view.width / 2, py - view.height / 2) < reach;
|
||||
});
|
||||
if (seen) return { view: restored, rotationRad };
|
||||
}
|
||||
const xs = nodes.map((vertex) => vertex[0]);
|
||||
const ys = nodes.map((vertex) => vertex[1]);
|
||||
|
||||
@@ -94,7 +94,33 @@ const fresh = viewMod.openingView("p-none", meta, viewOf(1000, 700, 1, 0, 0), [
|
||||
[200300, 500300],
|
||||
[200600, 500500],
|
||||
]);
|
||||
const withSaved = viewMod.openingView("p-1", meta, viewOf(1000, 700, 1, 0, 0), [[200300, 500300]]);
|
||||
const withSaved = viewMod.openingView("p-1", meta, viewOf(1000, 700, 1, 0, 0), [
|
||||
[saved.cx, saved.cy],
|
||||
]);
|
||||
// ③-2 기억한 화면에 노선이 한 점도 안 보이면(밀려 저장된 화면) 버리고 노선에 맞춘다.
|
||||
const strayMemory = viewMod.createViewMemory("p-stray", () => ({
|
||||
cx: 201150,
|
||||
cy: 500850,
|
||||
pxPerMeter: 8,
|
||||
rotationDeg: 45,
|
||||
}));
|
||||
strayMemory.flush();
|
||||
const strayNodes = [
|
||||
[200300, 500300],
|
||||
[200400, 500350],
|
||||
];
|
||||
const stray = viewMod.openingView("p-stray", meta, viewOf(1000, 700, 1, 0, 0), strayNodes);
|
||||
const strayOnScreen = strayNodes.some(([x, y]) => {
|
||||
const [px, py] = render.metricToScreen(meta, stray.view, x, y);
|
||||
return px >= 0 && px <= 1000 && py >= 0 && py <= 700;
|
||||
});
|
||||
|
||||
// ③-3 창 크기가 바뀌어도(편집 중 resize) 가운데 · 배율이 그대로 — 편집 창 `resize()` 와 같은 셈.
|
||||
const zoomed = viewOf(1500, 1000, 6, -900, 400);
|
||||
const keptBefore = viewMod.captureView(meta, zoomed, 0);
|
||||
const shrunk = viewOf(1280, 760, zoomed.scale, zoomed.offsetX, zoomed.offsetY);
|
||||
const refit = { ...shrunk, ...viewMod.restoreSavedView(meta, shrunk, keptBefore) };
|
||||
const keptAfter = viewMod.captureView(meta, refit, 0);
|
||||
|
||||
// ④ 노드 끼우기·빼기 — 편집값 여섯 줄이 같은 자리에서 함께 움직인다.
|
||||
const columns = {
|
||||
@@ -123,6 +149,9 @@ process.stdout.write(
|
||||
storedKeys,
|
||||
fresh: { rotationRad: fresh.rotationRad, scale: fresh.view.scale },
|
||||
withSaved: { rotationRad: withSaved.rotationRad },
|
||||
stray: { rotationRad: stray.rotationRad, onScreen: strayOnScreen },
|
||||
keptBefore,
|
||||
keptAfter,
|
||||
afterInsert,
|
||||
afterRemove,
|
||||
}),
|
||||
|
||||
@@ -49,6 +49,18 @@ def test_보던_화면이_없으면_노선에_맞추고_회전_0(results):
|
||||
assert results["withSaved"]["rotationRad"] == pytest.approx(math.radians(30))
|
||||
|
||||
|
||||
def test_노선이_안_보이는_기억은_버리고_노선에_맞춤(results):
|
||||
assert results["stray"]["rotationRad"] == 0
|
||||
assert results["stray"]["onScreen"] is True
|
||||
|
||||
|
||||
def test_창_크기가_바뀌어도_가운데와_배율_그대로(results):
|
||||
before, after = results["keptBefore"], results["keptAfter"]
|
||||
assert after["cx"] == pytest.approx(before["cx"], abs=1e-6)
|
||||
assert after["cy"] == pytest.approx(before["cy"], abs=1e-6)
|
||||
assert after["pxPerMeter"] == pytest.approx(before["pxPerMeter"], rel=1e-9)
|
||||
|
||||
|
||||
def test_노드_끼우기_빼기는_편집값이_같은_자리로(results):
|
||||
inserted = results["afterInsert"]
|
||||
assert inserted["planned"][1] == [5, 5]
|
||||
|
||||
Reference in New Issue
Block a user