2025-03-12-國家資訊與地圖應用程式 -第二步
當然可以,下面是你這份 CountryInfo.vue
的程式碼逐行解釋,幫你了解每個區塊的 用途與原理。這會幫助你未來自己維護或擴充功能 🧠💡
🔷 <template>
區塊:畫面結構
1 2 3 4 5 6
| <template> <div> <h2>🌍 國家資訊與地圖應用程式</h2> <div id="map"></div> </div> </template>
|
說明:
🔷 <script setup>
區塊:邏輯程式
1
| import { onMounted } from 'vue'
|
✅ 匯入 onMounted()
:Vue 組件掛載到畫面時會執行的生命週期函式。
當地圖畫面 #map
被 Vue 渲染到畫面上後,這段程式碼就會開始執行。
🧱 地圖初始化 & 錯誤偵測
1 2 3 4
| try { if (!window.L) { throw new Error('Leaflet (L) 尚未載入') }
|
✅ 確保全域變數 L
存在,這是 Leaflet 的主函式(因為你是用 CDN,不是用 import
)
🗺️ 建立地圖
1
| const map = L.map('map').setView([20, 0], 2)
|
✅ 建立 Leaflet 地圖,並設定初始視角:
#map
:地圖插入的容器 ID
[20, 0]
:緯度 20、經度 0 → 大致上是非洲中間
2
:放大倍率,小數字表示縮得很遠(看整個世界)
🧱 加入底圖(OpenStreetMap)
1 2 3
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map)
|
✅ 這是 Leaflet 的底圖來源,使用 OpenStreetMap 的免費圖資。
{s}
、{z}
、{x}
、{y}
是地圖瓦片系統的變數。
🧩 設定 marker 圖示(避免顯示不出來)
1 2 3 4 5 6 7 8 9 10 11 12
| const iconUrl = 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png' const shadowUrl = 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png'
const DefaultIcon = L.icon({ iconUrl, shadowUrl, iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }) L.Marker.prototype.options.icon = DefaultIcon
|
✅ Leaflet 使用自己的 marker 圖示,但在 CDN 環境下常常「找不到圖示」。
這段程式明確指定圖示網址,並設定為預設圖示,解決圖示不見的問題。
🌍 抓國家資料(REST Countries API)
1 2
| const res = await fetch('https://restcountries.com/v3.1/all?fields=name,capital,latlng,flags,currencies') const countries = await res.json()
|
✅ 向 REST Countries API 請求所有國家資料,但只取需要的欄位,減少資料量:
name
:國家名稱
capital
:首都
latlng
:經緯度
flags
:國旗圖
currencies
:貨幣資料
🛡️ 防呆:API 回傳不是陣列
1 2 3 4
| if (!Array.isArray(countries)) { console.error('API 傳回的資料不是陣列:', countries) return }
|
✅ 確保 countries
是一個陣列,如果不是就跳出,避免 .forEach
出錯。
📌 加入每個國家的 marker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| countries.forEach((country) => { const latlng = country.latlng const name = country.name?.common || '未知' const capital = country.capital?.[0] || '未知' const flag = country.flags?.png || '' const currency = country.currencies ? Object.values(country.currencies)[0]?.symbol || '未知' : '未知'
if (latlng?.length === 2) { const marker = L.marker(latlng).addTo(map) marker.bindPopup(` <div style="text-align: center;"> <img src="${flag}" width="80"><br> <strong>${name}</strong><br> 首都:${capital}<br> 貨幣:${currency} </div> `) } })
|
說明:
- ✅
country.latlng
:marker 座標
- ✅
country.name.common
:常用名稱,例如「Taiwan」
- ✅
country.capital[0]
:首都
- ✅
country.flags.png
:國旗圖片
- ✅
currencies
:貨幣資訊是物件,先轉成陣列後取第 1 筆
- ✅
L.marker(latlng)
:建立 marker
- ✅
.bindPopup(...)
:點 marker 時會跳出 popup
🧯 捕捉錯誤
1 2 3
| } catch (err) { console.error('地圖初始化錯誤:', err) }
|
✅ 如果以上任何一段出錯,會把錯誤資訊顯示在開發者工具中,不會整個壞掉。
🎨 <style scoped>
區塊:樣式
1 2 3 4 5 6 7 8 9
| h2 { font-size: 30px; margin-bottom: 15px; }
#map { height: 90vh; width: 100%; }
|
h2
:讓標題看起來更大、漂亮
#map
:
- 高度設為 90vh(瀏覽器視窗 90% 高)
- 地圖才會顯示出來(Leaflet 需要容器高度)
✅ 總結
這個 CountryInfo.vue
:
功能 |
是否完成 |
世界地圖初始化 |
✅ |
使用 OpenStreetMap 當底圖 |
✅ |
使用 REST API 取得各國資料 |
✅ |
使用 CDN 版本的 Leaflet |
✅ |
在每個國家經緯度加 marker |
✅ |
點 marker 顯示國旗+首都+貨幣 |
✅ |
錯誤處理與防呆 |
✅ |