Skip to content

Geolocation API 取得裝置地理位置

注意

  • 主要在 https 支援使用,部分瀏覽器 http 無法使用。
  • 初次操作 響應 會比較久。

說明

Geolocation API 可以使 客戶端 根據網頁應用程式,提供「當前」裝置的地理位置,基於隱私原因,需要 客戶端 「許可」後才執行。

當前位置:

經度 n/a

緯度 n/a

定位時間 n/a


監聽動態位置:

經度 n/a

緯度 n/a

變更定位時間 n/a

建立地理位置實體

可以依 navigator.geolocation 來取得「地理位置」的實體,後續依這個實體來做其它操作。

js
const Geolocation = navigator.geolocation

判斷瀏覽器支援

js
const Geolocation = navigator.geolocation

if (!Geolocation) {
  console.log('抱歉!瀏覽器不支援Geolocation')
}

取得當前地理位置

操作 .getCurrentPosition() 來取得裝置「當前」的地理位置,瀏覽器基於隱私會詢問 客戶端 是否同意提供,「同意」 才會提供相關的地理位置。

語法

Geolocation.getCurrentPosition( successCallback [, errorCallback] , [options] )

  • successCallback (成功)取得地理位置函式

  • errorCallback (失敗)取得地理位置函式

  • options 其它選項

    • maximumAge 緩存時效 (cache) (默認 0) 表示不使用緩存。

    • enableHighAccuracy 啟用高精準度 (默認 false)

      如果「啟用」 響應 時間上會增加、 消耗功率 也會增加,因為會使用到設備的 GPS 晶片。

    • timeout 逾時時間 (默認 Infinity)

      若超過時間沒有響應,就會進 errorCallback

Demo

js
// 地理位置實體
const Geolocation = navigator.geolocation

// 選項設置
const options = {
  timeout: 5000, // 響應超過 5秒 逾時 -> errorCallback
  enableHighAccuracy: true, // 使用高精度
}

// 成功執行函式
const successCallback = (info) => {
  console.log(info)
}

// 失敗執行函式
const errorCallback = (error) => {
  console.log(error)
}

// 取得當前地理位置功能
Geolocation.getCurrentPosition(successCallback, errorCallback, options)

callback response 響應

Success 成功取得

大部分會拿 經度緯度 來做後續的操作。

屬性說明
latitude緯度
longitude經度
altitude高度
accuracy位置誤差
altitudeAccuracy高度誤差
heading移動方向
speed移動速度
json
{
  "coords": {
    "accuracy": 17,
    "altitude": null,
    "altitudeAccuracy": null,
    "heading": null,
    "latitude": 25.056763, // 緯度
    "longitude": 121.518242, // 經度
    "speed": null
  },
  "timestamp": 1668145641823 // 取得位置時間戳
}

Error 取得失敗

  • 使用者「拒絕」提供地理位置:

    json
    {
      "code": 1,
      "message": "User denied Geolocation"
    }
    
  • 響應超時:

    json
    {
      "code": 3,
      "message": "Timeout expired"
    }
    

持續監聽位置

使用 geolocation.watchPosition() 持續監聽定位的變動,操作方法與 getCurrentPosition() 相同。

js
const geolocation = navigator.geolocation
geolocation.watchPosition(successEvent, errorEvent, options)

移除監聽

使用 geolocation.clearWatch() 來對持續監聽定位 watchPosition 回傳值 id 做「取消」。

js
const geolocation = navigator.geolocation
let id = geolocation.watchPosition(successEvent, errorEvent, options)

// 移除監聽
geolocation.clearWatch(id)

實例

CODE
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <style>
      * {
        padding: 0;
        list-style: none;
        background: #2e2e2e;
        color: #fff;
      }
      button {
        background: #fff;
        color: #2e2e2e;
        padding: 0.5rem 1rem;
        border: 1px solid #2e2e2e;
        border-radius: 8px;
      }
      ul {
        padding: 0.5rem 1rem;
        border: 1px solid #aaa;
        border-radius: 8px;
      }
      .ps-info {
        border-top: 1px solid #fff;
        margin-top: 0.5rem;
        padding-top: 0.5rem;
        font-size: 10px;
      }
    </style>
    <title>Static Template</title>
  </head>
  <body>
    <h1>Location Position</h1>

    <div class="location-info">
      <ul>
        <li>
          時間:
          <span id="time">--</span>
        </li>
        <li>
          經度:
          <span id="longitude">--</span>
        </li>
        <li>
          緯度:
          <span id="latitude">--</span>
        </li>
        <li>
          高度:
          <span id="altitude">--</span>
        </li>
        <li>
          速度:
          <span id="speed">--</span>
          <span>(m/s)</span>
        </li>
        <li>
          方向:
          <span id="heading">--</span>
        </li>
        <li class="ps-info">
          <div>
            位置誤差:
            <span id="accuracy">--</span>
          </div>
          <div>
            高度誤差:
            <span id="altitudeAccuracy">--</span>
          </div>
        </li>
      </ul>
      <button onclick="getCurrentLocation()">開始監聽位置</button>
      <button onclick="stopGetlocation()">停止監聽</button>
    </div>

    <script>
      const geolocationAPI = navigator.geolocation

      function setProps(propsEl, value) {
        const el = document.querySelector(`#${propsEl}`)
        el.textContent = value || 'n/a'
      }

      if (!geolocationAPI) {
        alert('抱歉! 瀏覽器不支援「定位服務」')
      }

      const options = {
        timeout: 5000, // 響應超過 5秒 逾時 -> errorCallback
        enableHighAccuracy: true, // 使用高精度
      }

      // 成功執行
      function getLocationSuccess({ timestamp, coords }) {
        console.log('success', coords)
        setProps('time', formatDate(timestamp)) // 時間
        setProps('longitude', coords.longitude) // 緯度
        setProps('latitude', coords.latitude) // 經度
        setProps('altitude', coords.altitude) // 高度
        setProps('speed', coords.speed) // 速度
        setProps('heading', coords.heading) // 方向 ( 0 度代表正北方向,90 度代表正東方向,180 度代表正南方向,270 度代表正西方向)
        setProps('accuracy', coords.accuracy) // 位置誤差
        setProps('altitudeAccuracy', coords.altitudeAccuracy) // 高度誤差
      }

      // 失敗執行
      function getLocationError() {
        alert('取得定位失敗!')
      }

      let watchId = null

      // 開始監聽定位功能
      function getCurrentLocation() {
        watchId = geolocationAPI.watchPosition(
          getLocationSuccess,
          getLocationError,
          options
        )
        alert('開始監聽位置')
      }

      // 停止監聽功能
      function stopGetlocation() {
        geolocationAPI.clearWatch(watchId)
        alert('已停止監聽位置')
      }

      // 格式時間功能
      function formatDate(timestamp) {
        const now = new Date(timestamp)
        return `${now.getFullYear()}/${
          now.getMonth() + 1
        }/${now.getDay()} ${now.getHours()}:${now.getMinutes()}`
      }
    </script>
  </body>
</html>

Reference