能力 · API
Geolocation API
发布于
navigator.geolocation 通过一次性的 getCurrentPosition() 或持续的 watchPosition() 报告设备位置(纬度、经度、精度半径,以及可选的海拔、航向和速度),前提是浏览器先弹出它自己的权限提示。没有任何同步返回值:结果和失败都通过你传入的回调送达。
各引擎很早就都支持了:Chrome 5、Firefox 3.5、Safari 5(iOS 3)。安全上下文要求是后来加的:Chrome 50、Firefox 55 与 Safari 10 对 localhost 以外的 http:// 源以 PERMISSION_DENIED 拒绝请求,但仍然暴露 navigator.geolocation(BCD api.Geolocation.secure_context_required)。GeolocationCoordinates.toJSON() 更新:Chrome 126、Firefox 129、Safari 18。
navigator.geolocation.getCurrentPosition(successCallback)navigator.geolocation.getCurrentPosition(successCallback, errorCallback)navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options)
navigator.geolocation.watchPosition(successCallback)navigator.geolocation.watchPosition(successCallback, errorCallback)navigator.geolocation.watchPosition(successCallback, errorCallback, options)
navigator.geolocation.clearWatch(watchId)getCurrentPosition() 返回 undefined。watchPosition() 返回一个大于零的 long 监视 id,位置每次变化都会调用 successCallback,直到调用 clearWatch(watchId);文档不是 fully active 时返回 0。不要求用户激活,但第一次请求不在用户激活内时 Chrome 会记录一条 [Violation](见实测)。
两个请求方法共用三个参数。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
successCallback |
PositionCallback |
是 | 接收 GeolocationPosition,含 coords(GeolocationCoordinates)与 timestamp(EpochTimeStamp)。 |
errorCallback |
PositionErrorCallback? |
否 | 接收带 code 与 message 的 GeolocationPositionError。不传时失败会被静默吞掉。 |
options |
PositionOptions |
否 | 下表的字典。 |
PositionOptions 有三个成员,都可选。
| 成员 | 类型 | 必填 | 说明 |
|---|---|---|---|
enableHighAccuracy |
boolean |
否 | 默认 false。提示使用可得的最精确来源(手机上是 GPS),代价是首次定位更慢、更耗电。缓存位置只有在其 [[isHighAccuracy]] 标志与此值一致时才会复用。 |
timeout |
[Clamp] unsigned long |
否 | 默认 0xFFFFFFFF 毫秒。开始获取位置后最多等待的时间;等待权限提示和等待隐藏文档变为可见的时间不计入。0 可能立即失败。 |
maximumAge |
[Clamp] unsigned long |
否 | 默认 0。接受不早于这么多毫秒的缓存位置;0 强制重新定位。 |
两个方法都不抛异常。失败以 GeolocationPositionError 送到 errorCallback,其 code 是该接口上三个常量之一。
code |
常量 | 条件 |
|---|---|---|
1 |
PERMISSION_DENIED |
用户或系统拒绝了权限;文档不允许使用 geolocation Permissions Policy 特性;或运行环境不是安全上下文。 |
2 |
POSITION_UNAVAILABLE |
文档不是 fully active;或底层系统获取位置失败。 |
3 |
TIMEOUT |
开始获取后 options.timeout 已超时。 |
message 是给开发者看的实现自定义文本,不适合展示给用户。Chrome 对权限失败报 User denied Geolocation,对 Permissions Policy 失败报 Geolocation has been disabled in this document by permissions policy.。用户给出的 PERMISSION_DENIED 会一直保持,直到用户自己更改设置;重复调用不会再次弹出提示。
每个示例都检查 "geolocation" in navigator,并在 API 缺失或请求失败时给用户手动提供位置的途径。由按钮触发请求能让提示符合预期,也避免 Chrome 的违规警告。
一次性定位,失败时回退到手动输入地址
Section titled “一次性定位,失败时回退到手动输入地址”timeout 与非零的 maximumAge 让请求不会在无法定位的设备上一直挂着。所有错误码都落到同一个回退:显示地址输入框。
const addressField = document.querySelector("#address");
function useManualEntry(reason) { addressField.hidden = false; addressField.placeholder = reason;}
document.querySelector("#use-location").addEventListener("click", () => { if (!("geolocation" in navigator)) { useManualEntry("请输入所在城市"); return; } navigator.geolocation.getCurrentPosition( ({ coords }) => { showNearby(coords.latitude, coords.longitude, coords.accuracy); }, (error) => { const reasons = { 1: "位置权限被拒绝", 2: "无法获取位置", 3: "定位超时" }; useManualEntry(reasons[error.code] ?? error.message); }, { enableHighAccuracy: false, timeout: 10_000, maximumAge: 60_000 }, );});coords.accuracy 是 95% 置信度的半径,单位米;「附近」类功能把几百米以内都视为足够,不必开 enableHighAccuracy。
跟踪路线,视图关闭时停止
Section titled “跟踪路线,视图关闭时停止”watchPosition() 会一直占用定位硬件直到 clearWatch() 运行,所以把监视绑定到需要它的界面的生命周期上。
let watchId = null;
function startTracking(onMove) { if (!("geolocation" in navigator)) return false; watchId = navigator.geolocation.watchPosition( (position) => onMove(position.coords), (error) => { stopTracking(); console.warn(`跟踪已停止:${error.code} ${error.message}`); }, { enableHighAccuracy: true, maximumAge: 0 }, ); return watchId !== 0;}
function stopTracking() { if (watchId !== null) navigator.geolocation.clearWatch(watchId); watchId = null;}
document.querySelector("#start").addEventListener("click", () => startTracking(updateMap));document.querySelector("#stop").addEventListener("click", stopTracking);window.addEventListener("pagehide", stopTracking);返回值为 0 表示请求监视时文档不是 fully active,函数直接报告失败,而不是等待一个可能不会到来的错误回调。
弹出提示前先查询权限状态
Section titled “弹出提示前先查询权限状态”navigator.permissions.query({ name: "geolocation" }) 读取状态而不触发提示,页面可以只在能成功时显示「使用我的位置」按钮,或者解释如何重新开启被拒绝的权限。
async function locationButtonState() { if (!("geolocation" in navigator)) return "unsupported"; if (!navigator.permissions) return "unknown"; // 点击时再请求并处理错误 const { state } = await navigator.permissions.query({ name: "geolocation" }); return state; // "granted" | "prompt" | "denied"}
const state = await locationButtonState();document.querySelector("#use-location").hidden = state === "unsupported" || state === "denied";document.querySelector("#denied-help").hidden = state !== "denied";"unknown" 分支针对有 geolocation 却没有 navigator.permissions 的旧 WebView;页面在那里回退为点击时请求并读取错误码。
- 通知权限模型,同一套
granted/prompt/denied模型在另一项能力上的应用 - Generic Sensor API 通用传感器,用于朝向与运动而非位置
- 本地网络访问,另一项受权限控制的能力
- Geolocation API: getCurrentPosition() method(w3.org)
- Geolocation API: PositionOptions dictionary(w3.org)
- Geolocation API(developer.mozilla.org)
规范
| 规范 | 状态 |
|---|---|
| Geolocation API(地理定位) | W3C |
| Geolocation API: getCurrentPosition() method | W3C |
| Geolocation API: watchPosition() method | W3C |
| Geolocation API: PositionOptions dictionary | W3C |
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| Chrome (Desktop) | 支持 | 5 | 高 | 来源 | — |
| Chrome (Android) | 支持 | 18 | 高 | 来源 | 1 |
| Edge (Desktop) | 支持 | 12 | 高 | 来源 | — |
| Firefox (Desktop) | 支持 | 3.5 | 高 | 来源 | 2 |
| Firefox (Android) | 支持 | 4 | 高 | 来源 | — |
| Safari (macOS) | 支持 | 5 | 高 | 来源 | — |
| Safari (iOS) | 支持 | 3 | 高 | 来源 | 3 |
| Samsung Internet | 支持 | 1.0 | 高 | 来源 | 4 |
| WebView (Android) | 支持 | 4.4 | 高 | 来源 | 5 |
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- Firefox 3.6 加入对 GPSD(https://gpsd.gitlab.io/gpsd/index.html,GPS 守护进程)的支持。基于 WiFi 的定位由 Google 提供(隐私说明:https://support.mozilla.org/en-US/kb/does-firefox-share-my-location-websites),或使用自定义提供方(MLS 说明:https://wiki.mozilla.org/CloudServices/Location/Software)。
- browser-compat-data 记录为 ≤3:在其跟踪的最早 iOS 版 Safari 中即已支持。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。