2025-03-12-國家資訊與地圖應用程式 -第二步

2025-03-12-國家資訊與地圖應用程式 -第二步

當然可以,下面是你這份 CountryInfo.vue 的程式碼逐行解釋,幫你了解每個區塊的 用途與原理。這會幫助你未來自己維護或擴充功能 🧠💡


🔷 <template> 區塊:畫面結構

1
2
3
4
5
6
<template>
<div>
<h2>🌍 國家資訊與地圖應用程式</h2>
<div id="map"></div>
</div>
</template>

說明:

  • h2 是標題,讓使用者知道這是什麼應用。

  • #map 是 Leaflet 地圖要掛載的位置(很重要!

    • Leaflet 會用 JavaScript 把地圖「插入」這個 DOM 元素中。

🔷 <script setup> 區塊:邏輯程式

1
import { onMounted } from 'vue'

✅ 匯入 onMounted():Vue 組件掛載到畫面時會執行的生命週期函式。


1
onMounted(async () => {

當地圖畫面 #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 顯示國旗+首都+貨幣
錯誤處理與防呆