diff --git a/CHANGELOG.md b/CHANGELOG.md index 64a0b89..2cb3ce6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ ## 2026-06-16 +### ๐ŸŽจ NaverMapView ์ฑ„๋„๋ณ„ ๋งˆ์ปค ์ƒ‰์ƒ (v0.1.60) +- GoogleMapView์™€ ๋™์ผ ํŒ”๋ ˆํŠธ (amber/blue/green/pink/purple/red/teal/yellow) +- ์‹๋‹น์˜ ์ฒซ ์ฑ„๋„ ๊ธฐ์ค€ ์ƒ‰์ƒ, activeChannel ์žˆ์œผ๋ฉด ๊ทธ ์ฑ„๋„ ์šฐ์„  + ### โšก NaverMapView SDK ๋„ค์ดํ‹ฐ๋ธŒ ๋งˆ์ปค + InfoWindow (v0.1.59) - ๋งˆ์ปค๋ฅผ React `absolute div` overlay โ†’ `naver.maps.Marker` ๋„ค์ดํ‹ฐ๋ธŒ๋กœ ๊ต์ฒด - ์คŒ/ํŒฌ ์‹œ SDK๊ฐ€ GPU ์ตœ์ ํ™”, ๋งค frame React ๋ฆฌ๋ Œ๋”๋ง ์—†์Œ โ†’ ๋ž™ ํ•ด์†Œ diff --git a/frontend/src/components/NaverMapView.tsx b/frontend/src/components/NaverMapView.tsx index cf481a6..c4d5aaa 100644 --- a/frontend/src/components/NaverMapView.tsx +++ b/frontend/src/components/NaverMapView.tsx @@ -44,6 +44,30 @@ type NaverInfoWindow = { const NAVER_CLIENT_ID = process.env.NEXT_PUBLIC_NAVER_MAP_CLIENT_ID || ""; +// Channel color palette โ€” GoogleMapView์™€ ๋™์ผ +const CHANNEL_COLORS = [ + { border: "#f59e0b" }, // amber (default) + { border: "#3b82f6" }, // blue + { border: "#22c55e" }, // green + { border: "#ec4899" }, // pink + { border: "#a855f7" }, // purple + { border: "#ef4444" }, // red + { border: "#14b8a6" }, // teal + { border: "#eab308" }, // yellow +]; + +function getChannelColorMap(restaurants: Restaurant[]) { + const channels = new Set(); + restaurants.forEach((r) => r.channels?.forEach((ch) => channels.add(ch))); + const map: Record = {}; + let i = 0; + for (const ch of channels) { + map[ch] = CHANNEL_COLORS[i % CHANNEL_COLORS.length]; + i++; + } + return map; +} + function useNaverMaps(): { ready: boolean; error: string | null } { const [ready, setReady] = useState(typeof window !== "undefined" && !!window.naver?.maps); const [error, setError] = useState(null); @@ -101,9 +125,9 @@ function getClusterSize(count: number): number { return 54; } -// SVG data URL โ€” ๋‹จ์ผ ๋งˆ์ปค(์ฃผํ™ฉ ํ•€) -function markerIconHtml(): string { - return `
`; +// ๋‹จ์ผ ๋งˆ์ปค โ€” ์ฑ„๋„ ์ƒ‰์ƒ๋ณ„ +function markerIconHtml(color: string): string { + return `
`; } // SVG data URL โ€” ํด๋Ÿฌ์Šคํ„ฐ(์ˆซ์ž) function clusterIconHtml(count: number, size: number): string { @@ -117,7 +141,9 @@ export default function NaverMapView({ onBoundsChanged, flyTo, onMyLocation, + activeChannel, }: MapViewProps) { + const channelColors = useMemo(() => getChannelColorMap(restaurants), [restaurants]); const { ready, error } = useNaverMaps(); const divRef = useRef(null); const mapRef = useRef(null); @@ -230,12 +256,14 @@ export default function NaverMapView({ markersRef.current.push(marker); } else { const r = (feature.properties as RestaurantProps).restaurant; + const chKey = activeChannel && r.channels?.includes(activeChannel) ? activeChannel : r.channels?.[0]; + const chColor = chKey ? channelColors[chKey] : CHANNEL_COLORS[0]; const marker = new naver.Marker({ position: new naver.LatLng(lat, lng), map: m, title: r.name, icon: { - content: markerIconHtml(), + content: markerIconHtml(chColor?.border ?? "#f59e0b"), anchor: new naver.Point(14, 14), }, }); @@ -252,7 +280,7 @@ export default function NaverMapView({ markersRef.current.push(marker); } } - }, [clusters, getExpansionZoom, onSelectRestaurant]); + }, [clusters, getExpansionZoom, onSelectRestaurant, channelColors, activeChannel]); // ์ปดํฌ๋„ŒํŠธ unmount ์‹œ ๋งˆ์ปค ์ •๋ฆฌ useEffect(() => {