Skip to content

HTML5 Geolocation API(地理定位)

HTML5 Geolocation API 允许网页访问用户的当前地理位置(经纬度)。这项技术广泛应用于地图导航、本地生活服务(外卖/打车)、运动轨迹记录等场景。

1. 核心对象

所有功能都挂载在 navigator.geolocation 对象上。

检测浏览器支持:

js
if ("geolocation" in navigator) {
  // 支持
} else {
  // 不支持
}

2. 三大核心方法

方法描述返回值
getCurrentPosition(success, error, options)获取一次当前位置。无 (undefined)
watchPosition(success, error, options)持续监听位置变化(像导航一样)。每当位置改变,回调就会执行。watchID (数字,用于取消监听)
clearWatch(watchID)停止监听

3. 参数详解

getCurrentPositionwatchPosition 接收相同的三个参数:

3.1 success 回调函数 (必填)

当获取位置成功时调用。接收一个 GeolocationPosition 对象。

返回的数据结构 (position):

属性说明备注
coords.latitude纬度十进制,如 39.9042
coords.longitude经度十进制,如 116.4074
coords.accuracy精度 (米)比如 50,表示真实位置在以坐标为圆心、50米为半径的圆内。
coords.altitude海拔高度 (米)如果设备不支持,返回 null
coords.altitudeAccuracy海拔精度 (米)如果设备不支持,返回 null
coords.heading前进方向 (度)0~360度(0为北)。移动中才有效,静止可能为 NaNnull
coords.speed速度 (米/秒)移动中才有效。
timestamp时间戳获取到位置的时间。

3.2 error 回调函数 (选填)

当获取位置失败时调用。接收一个 GeolocationPositionError 对象。

错误代码 (error.code):

代码 (Code)常量名含义
1PERMISSION_DENIED用户拒绝。用户点击了“禁止获取位置”。
2POSITION_UNAVAILABLE位置不可用。GPS 信号弱、网络断开等导致无法定位。
3TIMEOUT超时。在指定时间内未获取到位置。

3.3 options 配置对象 (选填)

属性类型默认值说明
enableHighAccuracyBooleanfalse是否开启高精度模式(如 GPS)。true 会更费电、更慢,但更准;false 通常使用 WiFi/IP 定位。
timeoutNumberInfinity超时时间 (毫秒)。如果超过这个时间没拿到位置,触发 Error (Code 3)。
maximumAgeNumber0缓存时间 (毫秒)。允许返回多久以前的历史位置。0 表示强制获取最新位置。

4. 完整代码示例

html
<button id="btn">获取我的位置</button>
<div id="output"></div>

<script>
const btn = document.getElementById('btn');
const output = document.getElementById('output');

btn.onclick = function() {
  if (!navigator.geolocation) {
    output.innerHTML = "您的浏览器不支持地理定位";
    return;
  }

  output.innerHTML = "定位中...";

  navigator.geolocation.getCurrentPosition(
    // 1. 成功回调
    (position) => {
      const lat = position.coords.latitude; // 纬度
      const lng = position.coords.longitude; // 经度
      const acc = position.coords.accuracy;  // 精度
      
      output.innerHTML = `
        <p>纬度: ${lat}</p>
        <p>经度: ${lng}</p>
        <p>精度: ${acc} 米</p>
        <p>注意:这是 WGS84 坐标,在中国地图上显示需要转换。</p>
      `;
    },
    // 2. 失败回调
    (error) => {
      switch(error.code) {
        case error.PERMISSION_DENIED:
          output.innerHTML = "用户拒绝了定位请求。";
          break;
        case error.POSITION_UNAVAILABLE:
          output.innerHTML = "位置信息不可用。";
          break;
        case error.TIMEOUT:
          output.innerHTML = "请求超时。";
          break;
        default:
          output.innerHTML = "未知错误: " + error.message;
      }
    },
    // 3. 配置项
    {
      enableHighAccuracy: true, // 尝试高精度
      timeout: 5000,            // 5秒超时
      maximumAge: 0             // 不读缓存
    }
  );
};
</script>

5. 常见问题 (FAQ) 与 避坑指南

5.1 为什么定位总是失败,或者没反应?

最常见原因:HTTPS 限制。 出于隐私安全考虑,现代浏览器(Chrome 50+)强制要求网站必须在 HTTPS 协议下才能使用 Geolocation API。

  • http://localhost (本地开发) 可以使用。
  • http://www.example.com (线上非安全域) 会被直接禁用,浏览器甚至不会弹窗询问。

5.2 坐标在中国地图(百度/高德)上显示偏了?(坐标系偏移问题)

这是中国开发者必须面对的核心问题。

  • HTML API 返回的坐标:标准 WGS-84 坐标系统(国际通用)。
  • 高德/腾讯地图:使用 GCJ-02 坐标系(火星坐标)。
  • 百度地图:使用 BD-09 坐标系。

后果:直接把 HTML 获取的 WGS-84 坐标填入百度地图,会偏差几百米甚至几公里

解法:必须使用第三方算法库(如 gcoord)或地图厂商提供的 API 接口进行坐标转换

  • WGS84 -> GCJ02 (用于高德)
  • WGS84 -> BD09 (用于百度)

5.3 为什么 getCurrentPosition 很慢?

  • 硬件预热:如果是冷启动,GPS 模块搜索卫星需要时间(几秒到几十秒)。
  • 精度权衡:如果你设置了 enableHighAccuracy: true,手机会尝试开启 GPS,这比 WiFi/基站定位慢得多。如果不需要米级精度,建议设为 false
  • 超时设置:建议设置合理的 timeout(如 5000ms),避免一直傻等。

5.4 怎么判断用户是在室内还是室外?

API 本身不直接告诉你。但可以通过 accuracy (精度) 属性推断:

  • 精度 < 20米:极大概率是 GPS 定位(通常在室外)。
  • 精度 > 100米:极大概率是 WiFi/基站定位(通常在室内或信号差的地方)。

5.5 为什么 watchPosition 即使我不动也会一直触发?

GPS 信号由于大气层干扰和多路径效应,读数会在小范围内漂移 (Drift)。即使手机静止,坐标也会在几米范围内跳动。

解法:在回调中计算新坐标与旧坐标的距离,如果小于某个阈值(如 10米),则忽略这次更新。

5.6 手机锁屏后,定位停止更新了?

是的。为了省电,移动端操作系统(iOS/Android)通常会在浏览器切到后台或锁屏后,挂起 Geolocation 服务。网页端很难实现完美的后台持续定位(这通常是 Native App 的特权)。

5.7 为什么 Error Code 是 2 (POSITION_UNAVAILABLE)?

  • 在电脑端:通常是因为连不上 Google 的定位服务(国内网络环境问题),导致 WiFi 定位失败。
  • 在手机端:可能是 GPS 信号被遮挡(地下室、电梯),或者用户在系统设置里关闭了浏览器的定位权限(不仅仅是网页弹窗权限,还有系统级的 App 权限)。