使用地理定位 API 我們可以向瀏覽器請求使用者的位置座標。

瀏覽器提供了一個 navigator.geolocation 對象,通過這個對象我們可以執行所有的地理定位操作。

由於安全性考慮,地理定位 API 只在使用 HTTPS 服務的頁面上可用,並且在所有現代瀏覽器上都可用。

navigator.geolocation

地理定位對象

由於 window 是全局對象,我們可以直接訪問 navigator 而無需指定 window.navigator

瀏覽器提供的 window.navigator 屬性指向一個名為 Navigator 對象 的容器對象,它使我們能夠使用許多 Web 平台 API。

geolocation 對象提供了以下方法:

  • getCurrentPosition()
  • watchPosition()
  • clearWatch()

第一個方法用於獲取當前的位置座標。當我們第一次調用此方法時,瀏覽器會自動要求用戶允許我們訪問此信息。以下是在 Chrome、Firefox 和 Safari 上展示此界面的示例:

Chrome 上的權限螢幕 Firefox 上的權限螢幕 Safari 上的權限螢幕

此操作只需在每個來源上執行一次。您可以更改您的決定,並撤消權限決策。以下示例演示如何在 Chrome 上進行更改:

權限詳細信息

一旦授予此權限,我們就可以繼續操作。

獲取使用者的位置

讓我們從以下示例代碼開始:

navigator.geolocation.getCurrentPosition(() => {})

應該會彈出權限窗格,請允許權限。

請注意,我傳遞了一個空的箭頭函數(arrow function),因為該函數需要一個回調函數。

此函數接收一個包含實際位置信息的 Position 對象:

navigator.geolocation.getCurrentPosition(position => {
 console.log(position)
})

此對象具有2個屬性:

  • coords,一個 Coordinates 對象
  • timestamp,獲取位置時的 UNIX 時間戳

Coordinates 對象具有幾個定義位置的屬性:

  • accuracy,位置測量值的精確度,以米為單位。
  • altitude,測量的高度值。
  • altitudeAccuracy,高度測量精確度,以米為單位。
  • heading,設備行進的方向。以度為單位表示(0 = 北,90 = 東,180 = 南,270 = 西)。
  • latitude,測量的緯度值。
  • longitude,測量的經度值。
  • speed,設備行進的速度,以米/秒為單位。

根據不同的實現和設備,其中一些屬性可能為 null。例如,在我的 MacBook Air 上運行的 Chrome 上,我只獲得了 accuracylatitudelongitude 的值。

navigator.geolocation.getCurrentPosition(position => {
 console.log(position.coords.latitude)
 console.log(position.coords.longitude)
})

監聽位置的變化

除了一次性獲取使用者位置(使用 getCurrentPosition()),您可以使用 navigator.geolocationwatchPosition() 方法來註冊一個回調函數,該函數將在設備通知我們每一次位置變化時調用。

用法:

navigator.geolocation.watchPosition(position => {
 console.log(position)
})

當然,如果之前尚未授予權限,瀏覽器也會對此方法進行權限要求。

我們可以通過調用 navigator.geolocation.clearWatch() 方法並傳遞 watchPosition() 返回的 id 來停止監聽位置的變化:

const id = navigator.geolocation.watchPosition(position => {
 console.log(position)
})

// 10秒後停止監聽
setTimeout(() => {
 navigator.geolocation.clearWatch(id)
}, 10 * 1000)

如果使用者拒絕了權限

還記得當我們調用 getCurrentPosition()watchPosition() 方法來獲取位置時,瀏覽器出現的權限彈出窗口嗎?

如果使用者拒絕了該權限,我們可以通過在這些方法的第二個參數中添加一個錯誤處理函數來處理這種情況。

navigator.geolocation.getCurrentPosition(position => {
 console.log(position)
}, error => {
 console.error(error)
})

傳遞給第二個參數的對象包含一個 code 屬性,用於區分不同的錯誤類型:

  • 1 表示權限被拒絕
  • 2 表示位置不可用
  • 3 表示超時

添加更多選項

在前面提到錯誤時,我提到了超時錯誤。獲取位置可能需要一些時間,我們可以通過在 getCurrentPosition()watchPosition() 方法中添加第三個參數(一個對象)來設置操作的最大時間。

您可以通過以下方式添加超時參數:

navigator.geolocation.getCurrentPosition(position => {
 console.log(position)
}, error => {
 console.error(error)
}, {
 timeout: 1000, // 設置超時時間(毫秒)
 maximumAge: 10000, // 設置緩存的最大“年齡”(毫秒)
 enableHighAccuracy: true // 默認為 false,設置為 true 時要求最高精度的位置(可能需要更多時間和能量)
})