Skip to content
Coding

歡迎來到 GIS 的世界- Day 25:旅遊規劃小專案的 網頁呈現

歡迎來到 GIS 的世界- Day 25:旅遊規劃小專案的 網頁呈現

有了 API 可以取得資料之後,接下來要使用 Leaflet 來把結果渲染出來。

Leaflet 的使用邏輯很簡單:

  1. 初始化
  2. 新增點位

1. 初始化

就像一開始提到的動詞 — — 渲染,要使用 Leaflet 前必須準備一個空間讓他發揮,於是我們建立一個空白的 div,也別忘記先把 css js 檔案的 CDN 掛載上去:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>旅遊規劃</title>
    
    <!-- Leaflet 的 CSS -->
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
          integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ=="
          crossorigin=""/>
    <style>
        
        /* 設定高度給 Leaflet 使用 */
        body{
            height: 98vh;
        }
        
        /* 設定高度給 Leaflet 使用 */
        #app, #map{
            height: 100%;
        }
    </style>
</head>
<body>
<!-- 搭配前端套件 Vue3 使用,所以另外建立一個 #app -->
<div id="app">
    
    <!-- 實際上放置 Leaflet 的地方 -->
    <div id="map"></div>
</div>

<!-- Leaflet 本體 -->
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
        integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
        crossorigin=""></script>
<!-- Axios(選用) -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    
<!-- Vue3(選用) -->
<script src="https://unpkg.com/vue@3"></script>
</body>
</html>

接著要來初始化地圖:

<!DOCTYPE html>
<html lang="en">
<body>
<!-- 前略 -->
<script>
    const app = Vue.createApp({
        data(){},
        methods:{
            initMap(data){
                // 初始化地圖
                
                // 'map' 中放入指定渲染節點的 id
                // setView([lat,lon]) 放入預設載入的中心位置
                let map = L.map('map').setView([24.175339, 120.648586], 19);
                
                // 新增 OSM 的圖磚
                L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
            },
            getScenicSpots(){
                // 取得景點資料
                axios({
                    method: 'get',
                    url: './api/ScenicSpot'
                }).then(res => {
                    this.initMap(res.data);
                }).catch(err => {
                    console.log(err);
                })
            },
        },
        mounted(){
            // Vue 掛載之後執行
            this.getScenicSpots();
        }
    });
    app.mount('#app');
</script>
</body>
</html>

成功載入的話會看到以逢甲附近為中心點的地圖,可以隨意縮放移動。

2. 新增點位

新增點位的方式很簡單,在載入圖磚之後把所有座標都利用 marker() 來建立成一個圖層之後,附加到原本的 map 上即可:

initMap(data){
    // 設定地圖
    let map = L.map('map').setView([24.175339, 120.648586], 19);
    
    // 新增圖磚
    L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
    
    // 建立點位
    let layer = data.map(ele => { L.marker([ele.y, ele.x]).addTo(map) });
    
    // 新增點位到圖磚上
    map.addLayer(layer);
}

成功執行的話,會看到原本地圖靠近中間底部的地方有一個點,他就是我們渲染出來的景點之一:

這個時候如果你努力的滾滑鼠滾輪,用力的把他們縮小,你會發現你的網頁變的很卡,然後密集恐懼症開始發作:

這種顯示方式太不優雅了!所以我們要利用 Leaflet 的套件 — — Leaflet.markercluster 來優化一下網頁的呈現。

Cluster 翻譯為叢集,這個套件的目的是讓我們把地圖縮小到一定比例的時候,幫助我們把多個目標合併成一個點,看起來會比較舒適,效果如下圖:

使用 markercluster

以下是縮放到不同尺寸的樣子:

initMap(data){
    let map = L.map('map').setView([24.175339, 120.648586], 19);
    L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
    
    // 原始
    // let coor = data.map(ele => { L.marker([ele.y, ele.x]).addTo(map) });
    // map.addLayer(coor);
    // Cluster
    
    let markers = L.markerClusterGroup();
    data.map(ele => { markers.addLayer(L.marker([ele.y, ele.x])) })
    map.addLayer(markers);
}

可以看到預設就會有不同顏色代表不同數量的呈現,並且移動到 cluster 上方還會很貼心的幫你標示出這個 cluster 所代表的區域,點擊之後會自動幫你 zoom in 🤩

當然顏色、標示這些功能都可以做調整,只是我會著墨在後端比較多,因此這篇文章只會介紹到這裡,其餘功能如果摸索上有問題,也歡迎留言一起討論喔。

References