From 1fd9f3da825cafa0636cfccd5a6aae30b45eab9c Mon Sep 17 00:00:00 2001 From: htlee Date: Mon, 16 Feb 2026 15:34:49 +0900 Subject: [PATCH] =?UTF-8?q?fix(map):=20fill=20=EB=8B=A8=EC=9D=BC=ED=99=94?= =?UTF-8?q?=20+=20globe=20=EB=B0=B0=EA=B2=BD=EC=83=89=20=EC=8B=AC=ED=95=B4?= =?UTF-8?q?=EC=83=89=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fill 3-tier 제거 → 단일 레이어(전체 depth) 복원 - setSky: sky/horizon/fog를 심해색(#010610)으로 설정 - 캔버스/map-area 배경: #010610 (타일 gap seam 비가시화) - 타일 경계 gap으로 배경이 비칠 때 색상 차이를 제거 Co-Authored-By: Claude Opus 4.6 --- apps/web/src/app/styles.css | 1 + .../web/src/widgets/map3d/hooks/useMapInit.ts | 20 +++++++++ .../map3d/hooks/useMapStyleSettings.ts | 12 +++-- .../src/widgets/map3d/layers/bathymetry.ts | 45 +++---------------- 4 files changed, 32 insertions(+), 46 deletions(-) diff --git a/apps/web/src/app/styles.css b/apps/web/src/app/styles.css index 462325f..c17d8d1 100644 --- a/apps/web/src/app/styles.css +++ b/apps/web/src/app/styles.css @@ -105,6 +105,7 @@ body { .map-area { position: relative; + background: #010610; } .sb { diff --git a/apps/web/src/widgets/map3d/hooks/useMapInit.ts b/apps/web/src/widgets/map3d/hooks/useMapInit.ts index 17261db..0a276fd 100644 --- a/apps/web/src/widgets/map3d/hooks/useMapInit.ts +++ b/apps/web/src/widgets/map3d/hooks/useMapInit.ts @@ -209,6 +209,26 @@ export function useMapInit( }, 60_000); map.once('load', () => { + // Globe 배경(타일 밖)을 심해 색상과 맞춰 타일 경계 seam을 비가시화 + try { + map!.setSky({ + 'sky-color': '#010610', + 'horizon-color': '#010610', + 'fog-color': '#010610', + 'fog-ground-blend': 1, + 'sky-horizon-blend': 0, + 'atmosphere-blend': 0, + }); + } catch { + // ignore + } + // 캔버스 배경도 심해색으로 통일 + try { + map!.getCanvas().style.background = '#010610'; + } catch { + // ignore + } + if (showSeamarkRef.current) { try { ensureSeamarkOverlay(map!, 'bathymetry-lines-coarse'); diff --git a/apps/web/src/widgets/map3d/hooks/useMapStyleSettings.ts b/apps/web/src/widgets/map3d/hooks/useMapStyleSettings.ts index 01b4282..9edefc9 100644 --- a/apps/web/src/widgets/map3d/hooks/useMapStyleSettings.ts +++ b/apps/web/src/widgets/map3d/hooks/useMapStyleSettings.ts @@ -114,13 +114,11 @@ function applyDepthGradient(map: maplibregl.Map, stops: DepthColorStop[]) { if (shallowest.depth < 0) { expr.push(0, lightenHex(shallowest.color, 1.8)); } - for (const layerId of ['bathymetry-fill', 'bathymetry-fill-medium', 'bathymetry-fill-deep']) { - if (!map.getLayer(layerId)) continue; - try { - map.setPaintProperty(layerId, 'fill-color', expr as never); - } catch { - // ignore - } + if (!map.getLayer('bathymetry-fill')) return; + try { + map.setPaintProperty('bathymetry-fill', 'fill-color', expr as never); + } catch { + // ignore } } diff --git a/apps/web/src/widgets/map3d/layers/bathymetry.ts b/apps/web/src/widgets/map3d/layers/bathymetry.ts index a1cb02e..9f38f38 100644 --- a/apps/web/src/widgets/map3d/layers/bathymetry.ts +++ b/apps/web/src/widgets/map3d/layers/bathymetry.ts @@ -10,9 +10,7 @@ export const SHALLOW_WATER_FILL_DEFAULT = '#14606e'; export const SHALLOW_WATER_LINE_DEFAULT = '#114f5c'; const BATHY_ZOOM_RANGES: BathyZoomRange[] = [ - { id: 'bathymetry-fill', mercator: [3, 7], globe: [3, 7] }, - { id: 'bathymetry-fill-medium', mercator: [7, 9], globe: [7, 9] }, - { id: 'bathymetry-fill-deep', mercator: [9, 24], globe: [9, 24] }, + { id: 'bathymetry-fill', mercator: [3, 24], globe: [3, 24] }, { id: 'bathymetry-borders-major', mercator: [3, 7], globe: [3, 7] }, { id: 'bathymetry-borders', mercator: [7, 24], globe: [7, 24] }, { id: 'bathymetry-lines-coarse', mercator: [5, 7], globe: [5, 7] }, @@ -113,47 +111,18 @@ export function injectOceanBathymetryLayers(style: StyleSpecification, maptilerK const depthIn = (depths: number[]) => ['in', depth, ['literal', depths]] as unknown[]; - // === Fill (contour polygons) — 3-tier LOD === - // 심해 폴리곤이 여러 벡터 타일에 걸칠 때 globe tessellation 타일 경계에서 - // seam 아티팩트 발생 → 줌아웃에서는 shallow만, 줌인에서 점진적으로 심해 포함 - const bathyFillPaint = { - 'fill-color': bathyFillColor, - 'fill-opacity': ['interpolate', ['linear'], ['zoom'], 0, 0.9, 5, 0.88, 8, 0.84, 10, 0.78], - }; - - // z3-7: depth >= -2000 (천해만 — 타일 seam 방지) + // === Fill (contour polygons) — 단일 레이어, 전체 depth === const bathyFill: LayerSpecification = { id: 'bathymetry-fill', type: 'fill', source: oceanSourceId, 'source-layer': 'contour', minzoom: 3, - maxzoom: 7, - filter: ['>=', depth, -2000] as unknown as unknown[], - paint: bathyFillPaint, - } as unknown as LayerSpecification; - - // z7-9: depth >= -4000 (중심해 포함) - const bathyFillMedium: LayerSpecification = { - id: 'bathymetry-fill-medium', - type: 'fill', - source: oceanSourceId, - 'source-layer': 'contour', - minzoom: 7, - maxzoom: 9, - filter: ['>=', depth, -4000] as unknown as unknown[], - paint: bathyFillPaint, - } as unknown as LayerSpecification; - - // z9+: 전체 depth (풀 디테일 — 뷰포트가 작아 타일 seam 무관) - const bathyFillDeep: LayerSpecification = { - id: 'bathymetry-fill-deep', - type: 'fill', - source: oceanSourceId, - 'source-layer': 'contour', - minzoom: 9, maxzoom: 24, - paint: bathyFillPaint, + paint: { + 'fill-color': bathyFillColor, + 'fill-opacity': ['interpolate', ['linear'], ['zoom'], 0, 0.9, 5, 0.88, 8, 0.84, 10, 0.78], + }, } as unknown as LayerSpecification; // === Borders (contour polygon edges) — 2-tier LOD === @@ -357,8 +326,6 @@ export function injectOceanBathymetryLayers(style: StyleSpecification, maptilerK const toInsert = [ bathyFill, - bathyFillMedium, - bathyFillDeep, bathyBordersMajor, bathyBorders, bathyLinesCoarse,