import { IconLayer, TextLayer } from '@deck.gl/layers'; import type { Layer, PickingInfo } from '@deck.gl/core'; import { svgToDataUri } from '../../utils/svgToDataUri'; import { iranOilFacilities } from '../../data/oilFacilities'; import type { OilFacility, OilFacilityType } from '../../types'; export { type OilFacility }; export const IRAN_OIL_COUNT = iranOilFacilities.length; const TYPE_COLORS: Record = { refinery: '#f59e0b', oilfield: '#10b981', gasfield: '#6366f1', terminal: '#ec4899', petrochemical: '#8b5cf6', desalination: '#06b6d4', }; function refinerySvg(color: string, size: number): string { return ` `; } function oilfieldSvg(color: string, size: number): string { return ` `; } function gasfieldSvg(color: string, size: number): string { return ` `; } function terminalSvg(color: string, size: number): string { return ` `; } function petrochemSvg(color: string, size: number): string { return ` `; } function desalinationSvg(color: string, size: number): string { return ` `; } type SvgFn = (color: string, size: number) => string; const TYPE_SVG_FN: Record = { refinery: refinerySvg, oilfield: oilfieldSvg, gasfield: gasfieldSvg, terminal: terminalSvg, petrochemical: petrochemSvg, desalination: desalinationSvg, }; const iconCache = new Map(); function getIconUrl(type: OilFacilityType): string { if (!iconCache.has(type)) { const color = TYPE_COLORS[type]; iconCache.set(type, svgToDataUri(TYPE_SVG_FN[type](color, 64))); } return iconCache.get(type)!; } function hexToRgba(hex: string, alpha = 255): [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, alpha]; } export interface IranOilLayerConfig { visible: boolean; sc: number; fs?: number; onPick: (facility: OilFacility) => void; } export function createIranOilLayers(config: IranOilLayerConfig): Layer[] { const { visible, sc, onPick } = config; const fs = config.fs ?? 1; if (!visible) return []; const iconLayer = new IconLayer({ id: 'iran-oil-icon', data: iranOilFacilities, getPosition: (d) => [d.lng, d.lat], getIcon: (d) => ({ url: getIconUrl(d.type), width: 64, height: 64, anchorX: 32, anchorY: 32 }), getSize: 18 * sc, updateTriggers: { getSize: [sc] }, pickable: true, onClick: (info: PickingInfo) => { if (info.object) onPick(info.object); return true; }, }); const labelLayer = new TextLayer({ id: 'iran-oil-label', data: iranOilFacilities, getPosition: (d) => [d.lng, d.lat], getText: (d) => d.nameKo.length > 10 ? d.nameKo.slice(0, 10) + '..' : d.nameKo, getSize: 12 * sc * fs, updateTriggers: { getSize: [sc] }, getColor: (d) => hexToRgba(TYPE_COLORS[d.type]), getTextAnchor: 'middle', getAlignmentBaseline: 'top', getPixelOffset: [0, 10], fontFamily: 'monospace', fontWeight: 600, fontSettings: { sdf: true }, outlineWidth: 8, outlineColor: [0, 0, 0, 255], billboard: false, characterSet: 'auto', }); return [iconLayer, labelLayer]; }