feature/dual-rendering #12
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, type MutableRefObject } from 'react';
|
import { useEffect, useMemo, type MutableRefObject } from 'react';
|
||||||
import maplibregl, {
|
import maplibregl, {
|
||||||
type GeoJSONSource,
|
type GeoJSONSource,
|
||||||
type GeoJSONSourceSpecification,
|
type GeoJSONSourceSpecification,
|
||||||
@ -54,6 +54,12 @@ export function useZonesLayer(
|
|||||||
) {
|
) {
|
||||||
const { zones, overlays, projection, baseMap, hoveredZoneId, mapSyncEpoch } = opts;
|
const { zones, overlays, projection, baseMap, hoveredZoneId, mapSyncEpoch } = opts;
|
||||||
|
|
||||||
|
// globe용 간소화 데이터를 미리 캐싱 — ensure() 내 매번 재계산 방지
|
||||||
|
const simplifiedZones = useMemo(
|
||||||
|
() => (zones ? simplifyZonesForGlobe(zones) : null),
|
||||||
|
[zones],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const map = mapRef.current;
|
const map = mapRef.current;
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
@ -75,26 +81,32 @@ export function useZonesLayer(
|
|||||||
zoneLabelExpr.push(['coalesce', ['get', 'zoneName'], ['get', 'zoneLabel'], ['get', 'NAME'], '수역']);
|
zoneLabelExpr.push(['coalesce', ['get', 'zoneName'], ['get', 'zoneLabel'], ['get', 'NAME'], '수역']);
|
||||||
|
|
||||||
const ensure = () => {
|
const ensure = () => {
|
||||||
if (projectionBusyRef.current) return;
|
// 소스 데이터 간소화 — projectionBusy 중에도 실행해야 함
|
||||||
|
// globe 전환 시 projectionBusy 가드 뒤에서만 실행하면 MapLibre가
|
||||||
|
// 원본(2100+ vertex) 데이터로 globe tessellation → 73,000+ vertex → 노란 막대
|
||||||
|
const sourceData = projection === 'globe' ? simplifiedZones : zones;
|
||||||
|
if (sourceData) {
|
||||||
|
try {
|
||||||
|
const existing = map.getSource(srcId) as GeoJSONSource | undefined;
|
||||||
|
if (existing) existing.setData(sourceData);
|
||||||
|
} catch { /* ignore — source may not exist yet */ }
|
||||||
|
}
|
||||||
|
|
||||||
const visibility: 'visible' | 'none' = overlays.zones ? 'visible' : 'none';
|
const visibility: 'visible' | 'none' = overlays.zones ? 'visible' : 'none';
|
||||||
// globe 모드에서 fill polygon은 tessellation으로 vertex 65535 초과 → 숨김
|
|
||||||
// (해안선 디테일 2100+ vertex가 globe에서 100,000+로 폭증하여 노란 막대 아티팩트 발생)
|
|
||||||
const fillVisibility: 'visible' | 'none' = projection === 'globe' ? 'none' : visibility;
|
const fillVisibility: 'visible' | 'none' = projection === 'globe' ? 'none' : visibility;
|
||||||
guardedSetVisibility(map, fillId, fillVisibility);
|
guardedSetVisibility(map, fillId, fillVisibility);
|
||||||
guardedSetVisibility(map, lineId, visibility);
|
guardedSetVisibility(map, lineId, visibility);
|
||||||
guardedSetVisibility(map, labelId, visibility);
|
guardedSetVisibility(map, labelId, visibility);
|
||||||
|
|
||||||
|
if (projectionBusyRef.current) return;
|
||||||
if (!zones) return;
|
if (!zones) return;
|
||||||
if (!map.isStyleLoaded()) return;
|
if (!map.isStyleLoaded()) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// globe: 서브샘플링된 데이터로 vertex 폭증 방지, mercator: 원본 데이터
|
// 소스가 아직 없으면 생성 (setData는 위에서 이미 처리됨)
|
||||||
const sourceData = projection === 'globe' ? simplifyZonesForGlobe(zones) : zones;
|
if (!map.getSource(srcId)) {
|
||||||
const existing = map.getSource(srcId) as GeoJSONSource | undefined;
|
const data = projection === 'globe' ? simplifiedZones ?? zones : zones;
|
||||||
if (existing) {
|
map.addSource(srcId, { type: 'geojson', data: data! } as GeoJSONSourceSpecification);
|
||||||
existing.setData(sourceData);
|
|
||||||
} else {
|
|
||||||
map.addSource(srcId, { type: 'geojson', data: sourceData } as GeoJSONSourceSpecification);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const style = map.getStyle();
|
const style = map.getStyle();
|
||||||
@ -247,5 +259,5 @@ export function useZonesLayer(
|
|||||||
return () => {
|
return () => {
|
||||||
stop();
|
stop();
|
||||||
};
|
};
|
||||||
}, [zones, overlays.zones, projection, baseMap, hoveredZoneId, mapSyncEpoch, reorderGlobeFeatureLayers]);
|
}, [zones, simplifiedZones, overlays.zones, projection, baseMap, hoveredZoneId, mapSyncEpoch, reorderGlobeFeatureLayers]);
|
||||||
}
|
}
|
||||||
|
|||||||
불러오는 중...
Reference in New Issue
Block a user