使用 Geolocation API 的簡單行程計量器

Michael Mahemoff
Michael Mahemoff

簡介

地理位置 API 可讓您找出使用者的位置,並在使用者移動時持續追蹤他們,但必須取得使用者同意。這項功能可用於使用者查詢,例如引導使用者前往目的地。這項功能也可以用來為使用者建立的部分內容加上「地理標記」,例如標示拍攝地點。這個 API 不受裝置限制,也不在乎瀏覽器如何判斷位置,只要用戶端可以以標準方式要求及接收位置資料即可。底層機制可能會透過 GPS、Wi-Fi 或要求使用者手動輸入位置。由於這些查詢都需要一些時間,因此 API 為非同步,您每次要求位置時都會傳遞回呼方法。

本例中的行程計里程表會顯示初始位置,並持續顯示自頁面載入後行程的距離。

步驟 1:確認相容性

Browser Support

  • Chrome: 5.
  • Edge: 12.
  • Firefox: 3.5.
  • Safari: 5.

Source

您可以輕鬆檢查相容性,方法是測試地理位置物件是否存在:

// check for Geolocation support
if (navigator.geolocation) {
  console.log('Geolocation is supported!');
}
else {
  console.log('Geolocation is not supported for this Browser/OS version yet.');
}

步驟 2:宣告 Trip Meter HTML

在本例中,您會建構行程計程器,因此請宣告下列 HTML:

<div id="tripmeter">
<p>
Starting Location (lat, lon):<br/>
<span id="startLat">???</span>°, <span id="startLon">???</span>°
</p>
<p>
Current Location (lat, lon):<br/>
<span id="currentLat">???</span>°, <span id="currentLon">???</span>°
</p>
<p>
Distance from starting location:<br/>
<span id="distance">0</span> km
</p>
</div>

接下來的幾個步驟會使用 Geolocation API 填入所有空白區間。

步驟 3:判斷使用者目前的位置

getCurrentPosition() 會以非同步方式回報使用者的目前位置。在網頁載入後立即呼叫,這樣系統就能正確填入 (並儲存供日後使用) 開始位置:

window.onload = function() {
var startPos;
navigator.geolocation.getCurrentPosition(function(position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
});
};

如果這是網域中應用程式首次要求權限,瀏覽器通常會檢查使用者是否同意。視瀏覽器而定,您可能還能設定一律允許或一律拒絕權限查詢,在這種情況下,系統會略過確認程序。

執行這段程式碼後,您應該會看到起始位置。根據瀏覽器使用的定位裝置,位置物件可能包含的資訊不只限於經緯度,例如可能包含高度或方向。您可以將位置變數記錄到控制台,進一步探索。

步驟 4:處理錯誤

很抱歉,並非所有位置查詢都能成功。可能是 GPS 無法定位,或是使用者突然停用位置查詢功能。在發生錯誤時,系統會呼叫 getCurrentPosition() 的第二個選用引數,因此您可以在回呼中通知使用者:

window.onload = function() {
var startPos;
navigator.geolocation.getCurrentPosition(function(position) {
// same as above
}, function(error) {
alert('Error occurred. Error code: ' + error.code);
// error.code can be:
//   0: unknown error
//   1: permission denied
//   2: position unavailable (error response from locaton provider)
//   3: timed out
});
};

步驟 5:監控使用者的位置

先前的 getCurrentPosition() 呼叫只會在網頁載入時執行一次。如要追蹤變更,請使用 watchPosition()。當使用者移動時,系統會自動通知回呼函式:

navigator.geolocation.watchPosition(function(position) {
document.getElementById('currentLat').innerHTML = position.coords.latitude;
document.getElementById('currentLon').innerHTML = position.coords.longitude;
});

步驟 6:顯示移動距離

這個步驟與 Geolocation API 並無直接關聯,但可讓您完成示範,並提供位置資料使用方式的範例。請在 watchPosition() 處理常式中新增一行,填入行進的距離:

navigator.geolocation.watchPosition(function(position) {
// same as above
document.getElementById('distance').innerHTML =
    calculateDistance(startPos.coords.latitude, startPos.coords.longitude,
                    position.coords.latitude, position.coords.longitude);
});

calculateDistance() 函式會執行幾何演算法,判斷兩個座標之間的距離。我們採用 Moveable Type 提供的程式碼,並根據 Creative Commons 授權實作 JavaScript:

function calculateDistance(lat1, lon1, lat2, lon2) {
var R = 6371; // km
var dLat = (lat2 - lat1).toRad();
var dLon = (lon2 - lon1).toRad();
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
}
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}