April 8, 2020

Leaflet 開源地圖:即時定位與距離計算

watchPosition web 原生定位函式


文 / 西打藍 Siddharam

前言


因為專案原因,需要在網頁上即時定位,並顯示和建築物的相對距離,索性就來研究開源地圖 Leaflet。

以前曾用過 Google Map API,它的功能是最多最齊全的,但因為要收費,所以才選擇 Leaflet。Leaflet 的特色是容易上手,也能滿足基本功能。

例如即時定位、測距、回傳經緯度等,以及常用的地點標註、圖表化、第三方介接,基礎應用皆能做到。接著來寫 code 吧。

leaflet


首先先引入 leaflet 套件:



<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>

...

// 放置地圖的元素

<div id='map'></div>

...



接著使用 mapbox 初始化地圖:



// map 是元素 id

var map = L.map('map')

L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
    maxZoom: 18,
    attribution: 'Map data © OpenStreetMap contributors, ' +
        'CC-BY-SA, ' +
        'Imagery © Mapbox',
    id: 'mapbox/streets-v11',
    tileSize: 512,
    zoomOffset: -1
}).addTo(map);

// setView 可以設定地圖座標
// watch 則是持續監聽使用者的位置

map.locate({setView: true, watch: true});



監聽使用者的即時位置:



// 成功監聽到使用者的位置時觸發
map.on('locationfound', onLocationFound);

// 失敗時觸發
map.on('locationerror', onLocationError);

function onLocationFound(e) {

}

function onLocationError(e) {

}



我們可以抓取當前位置,並計算與某地的距離:



function onLocationFound(e) {
  var myLocation = e.latlng // 使用者位置
 var bookstore = L.latLng(25.129836537742896, 121.74017250433087) // 書店
  console.log(myLocation.distanceTo(bookstore)) // 計算使用者和書店的距離
}



我是如何知道某地的經緯度?用 click 函式取得:



function onMapClick(e) {
    // 顯示點擊區域的經緯度
    alert("You clicked the map at " + e.latlng);
}

mymap.on('click', onMapClick);



如果想加標記,也很容易:



var marker = L.marker([51.5, -0.09]).addTo(map);



最後分享一個 Web 原生定位 API watchPosition:



var id, target, options;

function success(pos) {
    var crd = pos.coords;
    console.log(pos)
    // 取得經緯度
    console.log(pos.coords.latitude)
    console.log(pos.coords.longitude)

    if (target.latitude === crd.latitude && target.longitude === crd.longitude) {
        console.log('Congratulations, you reached the target');
        navigator.geolocation.clearWatch(id);
    }
}

function error(err) {
    console.warn('ERROR(' + err.code + '): ' + err.message);
}

target = {
    latitude : 0,
    longitude: 0
};

options = {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 0
};

id = navigator.geolocation.watchPosition(success, error, options);



結語


我猜 leaflet 的定位方式,是用原生語法 watchPosition 製作而成的,如果單純只需取得使用者定位,可能連 leaflet 也不需使用,只要原生語法就行了。




閱讀量




聯絡與合作


訂閱電子報,領「我當前 10+ 以上收入源有哪些」一文。

有文字採訪、網站開發,或是諮詢需求,皆可至個人網站參考作品,並聯繫 IG

或是想分享心情、聊聊天、交朋友,可以來秘密通道找我唷。

Email: frank@siddharam.com