跳转到内容

能力 · API

Geolocation API

发布于

自 2015-07 起广泛可用W3C

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。

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,函数直接报告失败,而不是等待一个可能不会到来的错误回调。

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;页面在那里回退为点击时请求并读取错误码。

规范

规范状态
Geolocation API(地理定位)W3C
Geolocation API: getCurrentPosition() methodW3C
Geolocation API: watchPosition() methodW3C
Geolocation API: PositionOptions dictionaryW3C
  • 图例
  • 支持
  • 部分支持
  • 需开启标志
  • 不支持
  • 未知
浏览器 / 平台支持版本置信度来源备注
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
  1. 由 browser-compat-data 镜像自 Chrome 的数据推导。
  2. 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)。
  3. browser-compat-data 记录为 ≤3:在其跟踪的最早 iOS 版 Safari 中即已支持。
  4. 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
  5. 由 browser-compat-data 镜像自 Chrome Android 的数据推导。

源数据: /compatibility/geolocation.json · 全球使用占比: 93 % (StatCounter 2026-05)

来源: 规范 · MDN · 最近核验 2026-10-03 · 置信度: 高 (由来源计算)