Skip to content

HTML5 - 地理位置

HTML5 Geolocation API 提供了一种标准方法,允许 Web 应用程序在用户明确许可的情况下访问用户的地理位置。这使得位置感知功能成为可能,例如查找附近的兴趣点、提供导航、为内容添加地理标签,或根据区域定制内容。

该 API 利用设备和浏览器可用的各种数据源,如 GPS(最准确,通常在移动设备上)、Wi-Fi 网络定位、蜂窝基站三角测量或 IP 地址查找(最不准确)来工作。

隐私至关重要: 浏览器必须先获得用户的许可,才能与网站共享位置数据。用户可以拒绝许可,API 提供处理此类拒绝的机制。

通过 navigator.geolocation 对象访问 Geolocation API。你应该首先检查此对象是否存在,以确保浏览器支持。

if ('geolocation' in navigator) {
// Geolocation is supported
console.log('Geolocation API available.');
// Proceed to use the API methods...
} else {
// Geolocation is not supported by this browser
console.error('Geolocation API is not available in this browser.');
// Inform the user or disable location features
}

navigator.geolocation 对象提供了三个主要方法:

方法描述
getCurrentPosition(successCallback, [errorCallback], [options])作为一次性请求检索设备的当前位置。成功时调用 successCallback 并传入一个 GeolocationPosition 对象;失败时调用 errorCallback 并传入一个 GeolocationPositionError 对象。
watchPosition(successCallback, [errorCallback], [options])持续监测设备位置,并在位置显著变化时调用 successCallback。返回一个 ID 值,可用于停止监测。
clearWatch(watchId)使用由 watchPosition() 返回的 ID 停止由该调用启动的正在进行的定位监测过程。

GeolocationPosition 对象(成功回调)

Section titled “GeolocationPosition 对象(成功回调)”

传递给 getCurrentPosition 或 watchPosition 的 successCallback 函数接收一个包含位置信息的 GeolocationPosition 对象:

属性类型描述
coords对象 (GeolocationCoordinates)包含地理坐标和精度信息。
coords.latitudeNumber纬度,以十进制度表示。
coords.longitudeNumber经度,以十进制度表示。
coords.accuracyNumber纬度和经度估计的精度,以米为单位。
coords.altitudeNumber | null[可选] 海拔高度,以 WGS 84 椭球体上方米为单位,如果不可用则为 null。
coords.altitudeAccuracyNumber | null[可选] 海拔高度估计的精度,以米为单位,如果不可用则为 null。
coords.headingNumber | null[可选] 行进方向,以度为单位(0=北,90=东等),如果不可用则为 null。
coords.speedNumber | null[可选] 当前地面速度,以米/秒为单位,如果不可用则为 null。
timestampNumber (DOMTimeStamp)检索位置信息的时间(自 epoch 以来的毫秒数)。
function handleSuccess(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const accuracy = position.coords.accuracy;
const timestamp = new Date(position.timestamp);
console.log(`Latitude: ${latitude}°`);
console.log(`Longitude: ${longitude}°`);
console.log(`Accuracy: ${accuracy} meters`);
console.log(`Timestamp: ${timestamp.toLocaleString()}`);
// Update UI, show map, etc.
document.getElementById('locationInfo').innerHTML =
`Lat: ${latitude.toFixed(5)}, Long: ${longitude.toFixed(5)} (Accuracy: ${accuracy}m)`;
}
function handleError(error) {
let errorMessage = 'An unknown error occurred.';
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage = "User denied the request for Geolocation.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "Location information is unavailable.";
break;
case error.TIMEOUT:
errorMessage = "The request to get user location timed out.";
break;
case error.UNKNOWN_ERROR:
errorMessage = "An unknown error occurred.";
break;
}
console.error(`Geolocation Error (${error.code}): ${errorMessage}`);
document.getElementById('locationInfo').textContent = `Error: ${errorMessage}`;
}
function getLocation() {
if ('geolocation' in navigator) {
document.getElementById('locationInfo').textContent = 'Requesting location...';
navigator.geolocation.getCurrentPosition(handleSuccess, handleError, {
enableHighAccuracy: true, // Request more accurate position (might use more power)
timeout: 10000, // Maximum time (ms) to wait for a position
maximumAge: 0 // Don't use a cached position, get a fresh one
});
} else {
document.getElementById('locationInfo').textContent = 'Geolocation is not supported by your browser.';
}
}

GeolocationPositionError 对象(错误回调)

Section titled “GeolocationPositionError 对象(错误回调)”

可选的 errorCallback 函数在定位检索失败时接收一个 GeolocationPositionError 对象:

属性类型描述
codeNumber表示错误类型的数字代码(见下文)。
messageString对错误的易读描述。

可能的错误码 (error.code):

代码常量描述
1PERMISSION_DENIED用户拒绝授予权限。
2POSITION_UNAVAILABLE网络不可用或无法获得卫星定位。
3TIMEOUT在确定位置之前请求超时。

getCurrentPosition 和 watchPosition 的可选第三个参数是一个 PositionOptions 对象:

属性类型默认值描述
enableHighAccuracyBooleanfalse表示应用程序偏好尽可能准确的结果。这可能会消耗更多电量(例如,启用 GPS)并花费更长时间。设置为 false 可以让设备省电。
timeoutNumberInfinity设备允许返回位置的最长时间,以毫秒为单位。如果花费时间超过此值,则调用 errorCallback,错误码为 TIMEOUT。
maximumAgeNumber0指定应用程序愿意接受的缓存位置的最大时效(以毫秒为单位)。设置为 0 以强制检索新的位置。设置为 Infinity 以接受任何缓存位置,无论其时效如何。
<!DOCTYPE html>
<html>
<head>
<title>Geolocation Example</title>
<style>
body { font-family: sans-serif; }
#locationInfo { margin-top: 10px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; }
</style>
</head>
<body>
<h1>HTML5 Geolocation</h1>
<button onclick="getLocation()">Get My Location</button>
<button onclick="watchLocation()">Watch My Location</button>
<button onclick="stopWatching()">Stop Watching</button>
<div id="locationInfo">Click 'Get My Location' or 'Watch My Location'.</div>
<script>
let watchId = null;
function handleSuccess(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const accuracy = position.coords.accuracy;
const timestamp = new Date(position.timestamp);
console.log("Position Update:", position);
document.getElementById('locationInfo').innerHTML =
`Lat: ${latitude.toFixed(5)}, Long: ${longitude.toFixed(5)}<br>
Accuracy: ${accuracy} meters<br>
Timestamp: ${timestamp.toLocaleString()}`;
}
function handleError(error) {
let errorMessage = 'An unknown error occurred.';
// ... (error handling switch statement as above) ...
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage = "User denied the request for Geolocation.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "Location information is unavailable.";
break;
case error.TIMEOUT:
errorMessage = "The request to get user location timed out.";
break;
case error.UNKNOWN_ERROR:
errorMessage = "An unknown error occurred.";
break;
}
console.error(`Geolocation Error (${error.code}): ${errorMessage}`);
document.getElementById('locationInfo').textContent = `Error: ${errorMessage}`;
}
const options = {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
};
function getLocation() {
if ('geolocation' in navigator) {
document.getElementById('locationInfo').textContent = 'Requesting location...';
navigator.geolocation.getCurrentPosition(handleSuccess, handleError, options);
} else {
document.getElementById('locationInfo').textContent = 'Geolocation is not supported.';
}
}
function watchLocation() {
if ('geolocation' in navigator) {
if (watchId) {
console.log("Already watching location.");
return;
}
document.getElementById('locationInfo').textContent = 'Watching location...';
// Start watching, store the returned ID
watchId = navigator.geolocation.watchPosition(handleSuccess, handleError, options);
console.log("Started watching location with ID:", watchId);
} else {
document.getElementById('locationInfo').textContent = 'Geolocation is not supported.';
}
}
function stopWatching() {
if (watchId !== null && 'geolocation' in navigator) {
navigator.geolocation.clearWatch(watchId);
console.log("Stopped watching location with ID:", watchId);
document.getElementById('locationInfo').textContent = 'Stopped watching location.';
watchId = null;
} else {
console.log("Not currently watching location.");
}
}
</script>
</body>
</html>