fix(B05): 종단 새 창 최대화 때 휠 이동 — 스크롤러가 놓인 창의 화면 틀 · 시계 사용(230-1)

메인 창 requestAnimationFrame 은 새 창 최대화로 메인 창이 가려지면 멈춤 · 휠은 막히고 이동 0.
휠 이동 · 끌기 뒤 클릭 삼킴 · 글자 선택 풀기 · 스크롤 뒤 다시 그리기 시계를 ownerDocument.defaultView 로.
새 시험 test_230_1_popout_wheel(가려진 메인 창 · 새 창 보통 · 최대화 · 원래 창).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3mdb91125mPoC6tpsQx4P
This commit is contained in:
2026-10-10 17:42:52 +09:00
co-authored by Claude Opus 5.5
parent dc027cd738
commit dd483a8fbd
4 changed files with 240 additions and 7 deletions
+5 -2
View File
@@ -29,15 +29,18 @@ export function bindProfileViewport(deps: ProfileViewportDeps): () => void {
/** 마지막으로 통째로 다시 만든 가로 위치 — 같은 자리면 다시 그리지 않는다. */
let settledScrollLeft = 0;
let scrollSettleTimer = 0;
/** 시계를 건 창 — 새 창으로 빼면 그 창 시계를 쓴다(가려진 메인 창 시계는 늦게 돎 · 230-1). */
let timerView: Window = window;
// 세로 맞춤은 **그리기가 아니라 변환**이다(2026-09-04 사용자 확정) — 스크롤마다 겹 하나의
// 변환만 갈아 끼우므로 실시간으로 따라온다. 눈금 간격이 어긋나면 눈금층(요소 20개 안팎)만
// 새로 만든다. 그래프를 통째로 다시 만드는 34ms 짜리 재구성은 그래도 안 될 때만 남는다.
body.addEventListener("scroll", () => {
if (deps.editing()) return;
const fitted = deps.fitElevation();
window.clearTimeout(scrollSettleTimer);
timerView.clearTimeout(scrollSettleTimer);
if (!needsFullRedraw(fitted)) return;
scrollSettleTimer = window.setTimeout(() => {
timerView = body.ownerDocument.defaultView ?? window;
scrollSettleTimer = timerView.setTimeout(() => {
if (deps.editing() || Math.abs(body.scrollLeft - settledScrollLeft) < 1) return;
settledScrollLeft = body.scrollLeft;
deps.draw();