/** * 정적 레이어 팩토리 * * 주의: deck.gl Layer 인스턴스는 내부에 WebGL 프로그램/모델 캐시를 보유한다. * 싱글턴으로 공유하면 페이지 전환 시 이전 WebGL 컨텍스트의 stale 참조가 * 새 컨텍스트에서 재사용되어 "parameter 1 is not of type 'WebGLProgram'" 에러 발생. * → 매 호출마다 새 인스턴스 생성. deck.gl이 id 기반 diff로 GPU 전송을 최적화. */ import { PathLayer } from 'deck.gl'; import { EEZ_BOUNDARY, NLL_LINE, EEZ_STYLE, NLL_STYLE } from '../constants'; function toPath(points: readonly (readonly [number, number])[]): [number, number][] { return points.map(([lat, lng]) => [lng, lat]); } function hexToRgba(hex: string, opacity: number): [number, number, number, number] { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return [r, g, b, Math.round(opacity * 255)]; } const EEZ_DATA = [{ path: toPath(EEZ_BOUNDARY) }]; const NLL_DATA = [{ path: toPath(NLL_LINE) }]; const EEZ_COLOR = hexToRgba(EEZ_STYLE.color, EEZ_STYLE.opacity); const NLL_COLOR = hexToRgba(NLL_STYLE.color, NLL_STYLE.opacity); /** EEZ 경계선 레이어 생성 */ export function createEEZStaticLayer() { return new PathLayer({ id: 'eez-boundary', data: EEZ_DATA, getPath: (d: { path: [number, number][] }) => d.path, getColor: EEZ_COLOR, getWidth: EEZ_STYLE.weight * 2, widthUnits: 'pixels' as const, getDashArray: [6, 4], dashJustified: true, }); } /** NLL 경계선 레이어 생성 */ export function createNLLStaticLayer() { return new PathLayer({ id: 'nll-line', data: NLL_DATA, getPath: (d: { path: [number, number][] }) => d.path, getColor: NLL_COLOR, getWidth: NLL_STYLE.weight * 2, widthUnits: 'pixels' as const, getDashArray: [8, 4], dashJustified: true, }); } /** 정적 기본 레이어 배열 (EEZ + NLL) — 매 호출마다 새 인스턴스 */ export function createStaticLayers() { return [createEEZStaticLayer(), createNLLStaticLayer()]; }