🌎️HTML5中的地理定位API

455 阅读6分钟

Geolocation API 地理定位 API 允许用户在需要时向 Web 应用程序提供用户的地理位置。出于隐私原因,用户需要获得报告位置信息的权限。

我们可以通过 navigator.geolocation 来访问地理位置对象,geolocation 上面提供了一些访问用户位置的 API,下面看一下几个常用的方法:

  • getCurrentPosition 用来获取用户当前位置信息
  • watchPosition 检测位置变化,可以动态的获取用户的位置
  • clearWatch 方法用来取消 Geolocation.watchPosition() 方法指定的监听函数

注意:地理位置功能涉及用户隐私,出于安全考虑,当一个 Web 页尝试获取地理位置信息时,会请求用户批准地理位置访问权限。用户可能会拒绝,浏览器将不会共享你的定位数据。另外,该 API 只能在 HTTPS 环境使用。

获取用户的位置

getCurrentPosition

可以使用 navigator.geolocation.getCurrentPosition() 方法来获取用户的位置:

navigator.geolocation.getCurrentPosition(success, error, options)

该方法接受三个参数:

success用户同意给出位置时的回调函数,它的参数是一个 Position 对象
error用户拒绝给出位置时的回调函数,它的参数是一个 PositionError 对象。该参数可选
options参数对象,该参数可选

Position 对象的两个属性:

Position.coords返回一个 Coordinates 对象,表示当前位置的坐标
Position.timestamp返回一个对象,代表当前时间戳

PositionError 对象的两个属性:

PositionError.code:

整数,表示发生错误的原因

关联常量描述
1PERMISSION_DENIED表示无权限,有可能是用户拒绝授权
2POSITION_UNAVAILABLE表示无法获得位置,可能设备有故障
3TIMEOUT表示超时

PositionError.message:

只读属性,只能在安全上下文中(Secure context)使用。

返回一字符串,描述错误细节。请注意,该字符串主要用于调试,不会直接显示在用户界面上。

option 的三个属性:

enableHighAccuracy是否返回高精度结果。 如果设为 true,可能导致响应时间变慢或(移动设备的)功耗增加;反之,如果设为 false,设备可以更快速地响应。默认值为 false。
timeout正整数,表示等待查询的最长时间,单位为毫秒。默认值为 Infinity。
maximumAge正整数,表示可接受的缓存最长时间,单位为毫秒。如果设为 0,表示不返回缓存值,必须查询当前的实际位置;如果设为 Infinity,必须返回缓存值,不管缓存了多少时间。默认值为 0。

Coordinates【坐标】 对象

我们正是通过 Position.coords 属性来使用 Coordinates 对象,该坐标接口用于表示设备在地球上的位置和海拔,以及计算这些属性的精确度。

Coordinates.latitude纬度
Coordinates.longitude经度
Coordinates.altitude表示相对于海平面的位置海拔(单位:米)。如果实现无法提供数据,则此值可以为 null
Coordinates.accuracy表示经度和纬度属性的精度(单位:米)
Coordinates.altitudeAccuracy表示海拔的精度(单位:米)。此值可以为 null
Coordinates.speed表示设备的速度(单位:米/秒)。此值可以为 null
Coordinates.heading表示设备运行的方向(单位:度)。表示设备离正北方向有多远。0 度表示正北,方向是顺时针方向确定的(这意味着东是 90 度,西是 270 度)。如果 Coordinates.speed 为 0,heading 属性返回 NaN。如果设备无法提供标题信息,则此值为 null。

示例代码

function handleSuccess(data) {
  // timestamp 成功获取位置信息时的时间戳
  const { coords, timestamp } = data

  /*
  accuracy: 返回结果的精度(米)
  altitude: 相对于水平面的高度
  altitudeAccuracy: 返回高度的精度(米)
  heading: 主机设备的行进方向,从正北方向顺时针方向
  latitude: 纬度
  longitude: 经度
  speed: 设备的行进速度
  */

  const { accuracy, altitude, altitudeAccuracy, heading, latitude, longitude,speed } = coords

  let coordsObj = {
      timestamp: {
          title: '成功获取位置信息时的时间戳',
          value: timestamp
      },
      accuracy: {
          title: '返回结果的精度(米)',
          value: accuracy
      },
      altitude: {
          title: '相对于水平面的高度',
          value: altitude
      },
      altitudeAccuracy: {
          title: '返回高度的精度(米)',
          value: altitudeAccuracy
      },
      heading: {
          title: '主机设备的行进方向,从正北方向顺时针方向',
          value: heading
      },
      latitude: {
          title: '纬度',
          value: latitude
      },
      longitude: {
          title: '经度',
          value: longitude
      },
      speed: {
          title: '设备的行进速度',
          value: speed
      }
  }

  let geolocationE = document.querySelector('#geolocation-e')
  let _divE = ''
  for(let [i, v] of Object.entries(coordsObj)) {
      _divE += `<div>${i}=${v.value}<div style='color: gray;'>说明:${v.title}</div></div>`
  }

      geolocationE.innerHTML = _divE
  }


  function handleError(error) {
      switch (error.code) {
          case 1:
          console.log('位置服务请求被拒绝', error.message )
          break
          case 2:
          console.log('暂时获取不到位置信息', error.message)
          break
          case 3:
          console.log('获取信息超时', error.message)
          break
          case 4:
          console.log('未知错误', error.message)
          break
      }
  }

  const opt = {
      // 高精确度: true / false
      enableHighAccuracy: true,
      // 等待响应的最长时间 单位:毫秒
      timeout: 5 * 1000,
      // 应用程序愿意接受的缓存位置的最大年限
      maximumAge: 0
  }

  if (navigator.geolocation) {
      // 检测浏览器是否支持Geolocation API
      navigator.geolocation.getCurrentPosition(handleSuccess, handleError, opt)
  } else {
      alert('Geolocation is not supported in your browser')
  }

实时获取用户位置

Geolocation.watchPosition()

Geolocation.watchPosition()对象指定一个监听函数,每当用户的位置发生变化,就是自动执行这个函数。

navigator.geolocation.watchPosition(success[, error[, options]])

该方法接受三个参数:

success表示监听成功的回调函数,该函数可以传入一个 Position 对象作为参数
error可选,表示监听失败的回调函数,该函数可以传入一个 PositionError 对象作为参数
option可选,表示监听的参数配置对象

示例代码:

function watchPositonSuccess(data) {
    const { coords, timestamp } = data

    console.log('coords:', coords) // 定位
    console.log('timestamp:', timestamp)
}


function watchPositionError(data) {
    console.log('error', data)
}

if (navigator.geolocation) {
    // 检测浏览器是否支持Geolocation API
    const id = navigator.geolocation.watchPosition(watchPositonSuccess, watchPositionError, options)

    // navigator.geolocation.clearWatch(id) // 取消 Geolocation.watchPosition() 方法指定的监听函数。
} else {
    alert('Geolocation is not supported in your browser')
}

Geolocation.clearWatch()

Geolocation.clearWatch() 方法用来取消 Geolocation.watchPosition() 方法指定的监听函数。

navigator.geolocation.clearWatch(id)

该参数由 Geolocation.watchPosition() 返回的监听函数的编号获得。

兼容性

如今,大多数浏览器和移动设备都支持地理定位 API。以下是 Can I Use 给出的兼容情况:

截图时间:2023/8/17

坐标转换

从手机获得坐标是GPS坐标,需要进行坐标的转化。

GPS坐标转化为百度地图坐标

lbsyun.baidu.com/faq/api?tit…

调用接口获取百度坐标:

https://api.map.baidu.com/geoconv/v1/?coords=118.7626675912094,31.988594165316727&from=1&to=5&ak=oFctGbRvH1NLOzATN63u1NcluB1sFPZk

获取新的百度坐标:

百度坐标反查

api.map.baidu.com/lbsapi/getp…

勾选坐标反查

GPS坐标转化为高德坐标

申请坐标转换的服务

lbs.amap.com/api/webserv…

使用https运行代码

Geolocation API 需要使用https运行代码。

使用http-server搭建服务,运行项目。

ps:本机可以使用localhost

安装http-server

npm install -g http-server

安装openssl

下载地址:

slproweb.com/products/Wi…

安装需要的版本:

生成证书:

# 首先使用以下命令生成一个证书密钥对 key.pem 和 cert.pem,它将有效期约10年(准确地说是3650天)
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem

启动服务:

# 然后便可以起服务了 下面两个命令都可以,后者会自动打开默认浏览器运行页面
http-server -S
http-server -S -C cert.pem -o

资料:

HTML5 定位 —— Geolocation API的正确使用

Geolocation

lbs.amap.com/tools/picke…

api.map.baidu.com/lbsapi/getp…

原生APP和H5定位存在偏差?地图定位原理剖析

经纬度/GPS坐标查询地图地址在线工具

使用 http-server 在本地开启 https 服务

环境篇-Windows下安装OpenSSL

地图坐标系统(各种坐标系详解)?

附件:

📎geolocation.zip

语雀地址:www.yuque.com/fengjutian/… 《🌎️HTML5中的地理定位API》