Merge branch 'iipbs/sn/dev_kic' into iipbs/sn/dev
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# 시설물 레이어 트리 스크롤 유지 구현기록
|
||||
|
||||
## 작업 정보
|
||||
|
||||
- 작업일: 2026-07-20
|
||||
- 모드: `quick_vibe`
|
||||
- 범위: 프론트엔드
|
||||
|
||||
## 요구사항 및 원인
|
||||
|
||||
- 시설물 레이어 트리 하단의 체크박스를 변경해도 세로 스크롤이 현재 위치를 유지해야 한다.
|
||||
- 기존 `GisTree`는 체크 변경 후 부모 지도 화면과 하단 레이어 설정영역이 다시 렌더되지만, 스크롤 요소의 `scrollTop`을 별도로 보존하지 않아 위치가 초기화될 수 있었다.
|
||||
|
||||
## 변경 내용
|
||||
|
||||
- `GisTree`의 실제 세로 스크롤 요소를 ref로 추적한다.
|
||||
- 스크롤 이벤트에서 현재 `scrollTop`을 보관하고, 렌더 완료 직후 유효 범위 안에서 같은 위치를 복원한다.
|
||||
- API, DB, 백엔드 계약은 변경하지 않았다.
|
||||
|
||||
## 수정 파일
|
||||
|
||||
- `packages/common/business_components/src/ui/map/GisTree.js`
|
||||
|
||||
## 검증
|
||||
|
||||
- 공통 비즈니스 컴포넌트 로컬 `tsup` ESM/DTS 빌드 성공
|
||||
- `git diff --check` 성공
|
||||
- 로컬 `/map`은 인증되지 않은 브라우저 세션에서 로그인 화면으로 전환되어 실제 레이어 체크 검증은 후속 수동 확인으로 남겼다.
|
||||
|
||||
## 롤백
|
||||
|
||||
- `GisTree.js`의 스크롤 ref, 스크롤 이벤트 핸들러, `useLayoutEffect` 복원 로직을 제거한다.
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DndProvider,
|
||||
} from "@minoru/react-dnd-treeview";
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import React, { useEffect, useState, useRef, useCallback } from "react";
|
||||
import React, { useEffect, useLayoutEffect, useState, useRef, useCallback } from "react";
|
||||
|
||||
import { useGisContext } from "./Gis";
|
||||
import GisApp from "./lib/gis.core";
|
||||
@@ -66,6 +66,29 @@ export default React.memo(function GisTree({
|
||||
const targetNodesRef = useRef([]);
|
||||
const isPausedRef = useRef(false);
|
||||
const timeoutIdRef = useRef(null);
|
||||
// 체크 후 부모 설정영역까지 다시 렌더되어도 사용자가 보던 트리 위치를 유지한다.
|
||||
const layerPanelScrollRef = useRef(null);
|
||||
const layerPanelScrollTopRef = useRef(0);
|
||||
|
||||
const handleLayerPanelScroll = useCallback((event) => {
|
||||
layerPanelScrollTopRef.current = event.currentTarget.scrollTop;
|
||||
}, []);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const scrollContainer = layerPanelScrollRef.current;
|
||||
if (!scrollContainer) return;
|
||||
|
||||
const maxScrollTop = Math.max(
|
||||
0,
|
||||
scrollContainer.scrollHeight - scrollContainer.clientHeight
|
||||
);
|
||||
const nextScrollTop = Math.min(layerPanelScrollTopRef.current, maxScrollTop);
|
||||
|
||||
if (scrollContainer.scrollTop !== nextScrollTop) {
|
||||
scrollContainer.scrollTop = nextScrollTop;
|
||||
}
|
||||
layerPanelScrollTopRef.current = nextScrollTop;
|
||||
});
|
||||
|
||||
// =====================
|
||||
// 유틸리티: 트리 탐색 관련 함수들
|
||||
@@ -533,6 +556,8 @@ export default React.memo(function GisTree({
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
ref={layerPanelScrollRef}
|
||||
onScroll={handleLayerPanelScroll}
|
||||
className={`grow overflow-y-auto border-none p-2 ${showLayerPanelTitle ? "pt-0" : "pt-2"} shadow-none ${activeTab === "layers" ? "block" : "hidden"
|
||||
}`}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user