DEV Community

Cover image for OSM + Leaflet 學習筆記 1:建地圖、marker、事件、換圖層
Let's Write
Let's Write

Posted on • Edited on

OSM + Leaflet 學習筆記 1:建地圖、marker、事件、換圖層

本篇要解決的問題

之前有寫過一系列的 Google Maps API 學習筆記。Google Maps 好用,但過了一定的額度會收費,當時就有人留言問說免費地圖的事,有留上了心。

原本是直接找 OpenStreetMap 的 API,後來看到文件上回來的都是用 XML,實在是懶得處理轉 JSON 這段。之後幸運地找到一個可以接 OpenStreetMap 的 Leaflet,一個用 JavaScript 接 API 的開源碼,就翻了一下文件,整理成這篇。

本篇會示範的功能如下:

  1. 使用者請求地點,建立地圖
  2. 放置 + 客製 marker
  3. Popup
  4. Tooltip
  5. Map click event
  6. 外部 zoom in、zoom out
  7. 改變地圖樣式

本篇主要參考文件:Leaflet Quick Start Guide

後續各段會用到的參考文件,將寫在各段之中。

本篇最後會完成的 Demo:

https://letswritetw.github.io/letswrite-leaflet-osm-basic/


請求地點,建立地圖

跟 Google Maps API 一樣,Leaflet 在建立地圖時需要一個中心點。

跟使用者請求所在位置座的座標,需要使用者同意,因此也要先預設一個當使用者拒絕時,或是所擁有的裝置不支援提供所在座標時的地點。

本篇預設地點設為台北市立動物園~ 想去看水豚君啊~~~

關於找地點的座標,August 用的是比較簡單的方法,如果有人有更好的方法歡迎留言提供。

首先進到 Google Maps 的網站,搜尋想要知道座標的地點,我們這邊搜尋「動物園」後,選到動物園,接著按下資料卡片的「分享」:

點擊分享

接著點擊「複製連結」:

點擊「複製連結」

然後把複製的網址貼到瀏覽器上打開,短網址會回復成原網址,就能從網址中看見座標,像這樣:

從網址中看見座標

這是 August 知道不用接任何 API 就能找到一個地點座標的方式。

跟使用者要權限

當我們跟使用者要權限時,使用者會看到這樣的請求:

跟使用者要位置資訊

當使用者按下了「允許」,我們就可以得到使用者的座標,程式碼如下:

建立地圖

不管有沒有取到使用者的所在位置,都一樣可以建立 OpenStreepMap 的地圖。

首先先引用 CSS、JS:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js"></script>
Enter fullscreen mode Exit fullscreen mode

接著在我們要放置地圖的地方,放上一個空 div 並帶上我們指定的 id:

<div id="map"></div>
Enter fullscreen mode Exit fullscreen mode

下一步,給我們的 div 一個高度:

#map {
  height: 180px;
}
Enter fullscreen mode Exit fullscreen mode

高度的部份本篇的 Demo 是用 50vh,實際應用時依各頁面的狀況再作修改。

最後就是用 Leaflet 來建立地圖:

Options 的部份可自行參考 文件,這邊僅列出 August 覺得會用到的。

L.tileLayer 這個是指地圖要讀取哪一個樣式,文件中的預設樣式就是這個:

https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
Enter fullscreen mode Exit fullscreen mode

少了 tileLayer 地圖會是一片灰。

開啟頁面後,地圖就出來了:

建立地圖完成


放置 Marker

放置 marker 的方式就是新增一個出來後,add 到 map 裡,程式碼如下:

center 就是要放置的座標。

預設的 Maker 樣式如下:

預設的 Maker 樣式

客製 Maker 圖示

Marker 可以用客製的 icon,如下:

我們這邊多放置幾個來看:

客製 Marker

一次放置多個可以用迴圈,Demo 的原始檔會附上。

Marker 加上 Popup

Marker 能加上 Popup 跟 Tooltip。

Popup 可以預設打開。

openPopup() 就是打開 Popup。

Popup 長這個樣子:

Popup 樣式

Marker 加上 Tooltip

Tooltip 就是我們常見的 Tooltip(嗯?有寫跟沒寫一樣)。

一樣可以預設要不要打開,也可以設定顯示的位置:

Tooltip 長這樣:

Tooltip 樣式


Map 點擊事件

Leaflet 可以監聽 Map 的點擊。

在官方的範例就有示範點擊地圖後,加上一個 Popup 寫著此處座標,這邊 August 改寫一下:

隨便點擊地可上任一地方,就會出現寫著座標的 Popup:

點擊後顯示座標


zoom in, zoom out

除了地圖上預設的功能鍵,也可以用地圖外的按鈕,用 function 執行 zoom in、zoom out。

map.zoomIn(1);
map.zoomOut(1);
Enter fullscreen mode Exit fullscreen mode

數字是一次要 zoom 多少,實際測了一下,zoom 的值是 0 – 18。

0 是世界地圖,18 就是到街景了。


改變地圖樣式 Layer

參考:How to change base layer using JS and leaflet layers control

除了預設的地圖樣式,還有蠻多種樣式可以使用的,在 Leaflet Provider Demo 上可以看到多種,大部份也都有附上 Layer 的網址。

不過,有些不確定是否有收費,因為看到需要 token。

改變地圖樣式的按鈕,可以放在地圖之中,也可以在地圖之外放按鈕控制。

在地圖之內

在地圖之內,總覺得樣式有點陽春 XD~

但勝在方便。

把控制選項放在地圖上,長這樣:

地圖上有 Layer 的控制選項

Hover 時會秀出選單:

秀出 Layer 選單

實際使用,覺得切換的時間有點久,大家看 Demo 時要等一下。

最喜歡的是深色的一款 Stadia.AlidadeSmoothDark,不過這款免費使用下有限制,可以看 官網 說明。

在地圖之外

改變 Layer 主要是這行:

L.tileLayer('layer 的 url').addTo(map);
Enter fullscreen mode Exit fullscreen mode

因此要用地圖外面的按鈕來切換地圖的樣式,只需要寫 click 時執行上面那行就行。


本篇 Demo 及原始碼

最後附上本篇的 Demo 網址,及原始碼的 Github 網址。

Demo:https://letswritetw.github.io/letswrite-leaflet-osm-basic/

Github:https://github.com/letswritetw/letswrite-leaflet-osm-basic

Top comments (0)