iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0

文章同步發表至 Medium

有了 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/leaflet@1.8.0/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/leaflet@1.8.0/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


上一篇
旅遊規劃小專案 2 - API
下一篇
旅遊規劃小專案 4 - 縣市找景點
系列文
歡迎來到 GIS 的世界!30 天從後端開始學 GIS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言