2025-03-13-Leaflet 是如何「插入地圖」的

2025-03-13-Leaflet 是如何「插入地圖」的

這兩個問題問得非常好!我們來一個一個解釋,保證你從底層原理完全理解:


✅ 1. #map 是 Leaflet 地圖要掛載的位置 — 什麼叫「插入 DOM」?插入後長怎樣?

🔍 Leaflet 是如何「插入地圖」的?

當你執行這段:

1
const map = L.map('map').setView([20, 0], 2)

Leaflet 會去 尋找這個 DOM 元素:

1
<div id="map"></div>

然後它就會用 JavaScript 動態地改寫這個 <div>,在裡面插入一堆 HTML 元素(還會加上樣式、影像、圖層等)來顯示地圖。


🔎 插入之後,#map 裡面長怎樣?

例如原本是:

1
<div id="map"></div>

執行後會變成這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="map" class="leaflet-container leaflet-touch leaflet-fade-anim ..." style="position: relative;">
<div class="leaflet-pane leaflet-map-pane">
<div class="leaflet-pane leaflet-tile-pane">
<div class="leaflet-layer">
<div class="leaflet-tile-container leaflet-zoom-animated">
<img src="https://tile.openstreetmap.org/2/1/1.png" ...>
<img src="https://tile.openstreetmap.org/2/2/1.png" ...>
...
</div>
</div>
</div>
<div class="leaflet-pane leaflet-overlay-pane"></div>
<div class="leaflet-pane leaflet-shadow-pane"></div>
<div class="leaflet-pane leaflet-marker-pane"></div>
<div class="leaflet-pane leaflet-tooltip-pane"></div>
<div class="leaflet-pane leaflet-popup-pane"></div>
</div>

<!-- 控制列、縮放按鈕等等 -->
<div class="leaflet-control-container">
...
</div>
</div>

Leaflet 幫你做了非常多事:

  • 加 tile 圖片(地圖切片)
  • 加 marker 圖層
  • 加縮放按鈕
  • 加動畫效果
  • 加事件處理(滑鼠拖拉、滾輪放大)

這就是所謂的「地圖被插入到這個 DOM 裡面」。


✅ 2. !window.L 為什麼代表 Leaflet 沒載入?

🔍 L 是什麼?為什麼是 Leaflet?

當你用 CDN 引入 Leaflet 時

1
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

這支 JS 裡面會自動把 L 註冊成全域變數,並把所有 Leaflet 的功能放進這個物件裡面。

例如:

1
console.log(window.L) // => Leaflet 物件

你可以試著列印出來看看:

1
console.log(L)

你會看到像這樣:

1
2
3
4
5
6
7
{
map: ƒ, // L.map(...)
marker: ƒ, // L.marker(...)
tileLayer: ƒ, // L.tileLayer(...)
icon: ƒ, // L.icon(...)
...
}

✅ 所以 !window.L 的意思是:

  • 「如果 window.L 不存在」(也就是 Leaflet 沒有正確載入)
  • 就顯示錯誤或中止程式
1
2
3
if (!window.L) {
throw new Error('Leaflet 尚未載入')
}

這樣做的目的是避免後面用 L.map(...) 時報錯 L is not defined


✅ 補充:為什麼我們不用 import L from 'leaflet'

因為你選擇了 CDN 模式(不用 npm 安裝),所以:

  • 我們不寫 import
  • 而是用 <script src="..."> 載入 Leaflet
  • 這會在全域自動建立 window.L

這種做法常見於:

  • 練習、教學
  • 無需打包的專案(例如 Replit、CodePen)

想要自己試看看?

你可以打開開發者工具,在 map 載入後打:

1
console.log(document.getElementById('map').innerHTML)

就可以看到 Leaflet 注入的 HTML 結構。