在現代 Web 開發中,地圖服務是許多應用的重要元件。本文將介紹如何在 Next.js 中使用 Google Maps API,並展示一個包含地圖標記和互動功能的範例。
設定 Google Maps API
1. 啟用 Google Maps API
第一步是前往 Google Cloud Console,開啟 Google Maps API 並建立 API 金鑰。記得限制金鑰的使用範圍以提高安全性。
2. 設定環境變數
將 API 金鑰儲存到 .env.local
檔案中,例如:NEXT_PUBLIC_MAPS_API_KEY=你的API金鑰
。
開發地圖元件
1. 安裝 Google Maps 套件
安裝必要的套件,包含 Google Maps API 的 Loader,以及 GeoJSON 的 TypeScript 型別支援套件:
npm install @googlemaps/js-api-loader @types/geojson
2. 建立地圖元件
以下是 Map
元件的完整程式碼,它負責載入地圖並顯示標記,同時也綁定了 Click 事件,後續可以再依照需求加上互動功能:
import { Loader } from '@googlemaps/js-api-loader'
import { FeatureCollection, Point } from 'geojson'
import { useEffect, useRef } from 'react'
interface MapProps {
mapData: FeatureCollection | null
handleClick: (marker: { lat: number; lng: number }) => void
}
const Map = ({ mapData, handleClick }: MapProps) => {
const mapRef = useRef<HTMLDivElement>(null)
useEffect(() => {
// Import needed libraries
const initMap = async () => {
const loader = new Loader({
apiKey: process.env.NEXT_PUBLIC_MAPS_API_KEY || '',
version: 'weekly',
libraries: ['places'],
})
const { Map } = await loader.importLibrary('maps')
const { AdvancedMarkerElement } = await loader.importLibrary('marker')
// Map options
const mapOptions: google.maps.MapOptions = {
center: {
lat: 22.61204890135084,
lng: 120.30288007791076,
},
zoom: 13,
mapTypeId: 'roadmap',
mapId: 'YOUR_MAP_ID',
}
// Setup the map
const map = new Map(mapRef.current as HTMLDivElement, mapOptions)
// Create markers
if (!mapData) return
mapData.features.forEach(feature => {
const coordinates = (feature.geometry as Point).coordinates
// Create custom pin element for each feature
const customPin = document.createElement('div')
customPin.innerHTML = `<div id="marker-${feature.properties?.id}">TEST</div>`
const faPin = new PinElement({
glyph: customPin,
})
const marker = new AdvancedMarkerElement({
map,
position: {
lat: coordinates[0], // 經度
lng: coordinates[1], // 緯度
},
title: `${feature.properties?.name} - ${feature.properties?.site}`,
content: faPin.element,
gmpClickable: true,
})
// Add a click listener for each marker
marker.addListener('click', () => {
// ...
// handle click event
})
})
}
initMap()
}, [mapData, handleClick])
return <div ref={mapRef} style={{ height: '500px', width: '100%' }} />
}
export default Map
3. 整合至頁面上
完成地圖元件後,就可以在 page.tsx
中呼叫 Map
元件,實際載入地圖:
'use client'
import { useState, useEffect } from 'react'
import Map from '@/features/map/components'
const HomePage = () => {
const [mapData, setMapData] = useState<FeatureCollection | null>(null)
useEffect(() => {
// 模擬 API 呼叫載入地圖資料
fetch('/api/map')
.then(res => res.json())
.then(data => setMapData(data))
}, [])
const handleMarkerClick = (marker: { lat: number; lng: number }) => {
console.log('Marker clicked:', marker)
}
return (
<div>
<h1>Google Maps in Next.js</h1>
{mapData ? (
<Map mapData={mapData} handleClick={handleMarkerClick} />
) : (
<p>Loading map...</p>
)}
</div>
)
}
export default HomePage
處理地圖資料
GeoJSON 是一種處理地理資訊的 JSON 格式,我們可以根據格式規範,建立以下地圖資料:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [120.30288, 22.61205] },
"properties": { "name": "Location 1", "site": "Site 1" }
}
]
}
可以使用 Next.js 的 API Route /api/map
模擬提供這些資料,並在地圖上渲染出標記。
結論
透過上述步驟,就可以在 Next.js 中成功整合 Google Maps API,實現地圖顯示、標記點擊等互動功能。這只是一個簡單的基礎實作,後續可以再進行更多擴展,像是整合更多自訂功能,例如搜尋和導航等等。