Geolocation API 使您能够在征得用户同意的情况下发现用户的位置。
Geolocation API 使您能够在征得用户同意的情况下发现用户的位置。此功能可用于指引用户到达目的地、为用户创建的内容添加地理位置标记(如标记照片拍摄地点)等。
借助 Geolocation API,您还可以查看用户所在的位置并密切关注他们的动向,这一切都要征得用户同意(并且仅在网页打开时有效)。这会创建许多有趣的用例,例如与后端系统集成,当用户在附近时准备订单以便取货。
使用 Geolocation API 时,您需要注意许多事项。本指南将向您介绍常见的使用场景和解决方案。
摘要
- 在对用户有益时使用地理定位。
- 通过请求权限来明确响应用户手势。
- 如果用户的浏览器不支持地理定位,请使用功能检测。
- 不要仅仅学习如何实现地理定位,还要学习使用地理定位的最佳方法。
- 测试网站的地理定位功能。
何时使用地理定位
- 查找用户最接近特定实际位置的位置,以定制用户体验。
- 根据用户的位置定制信息(例如新闻)。
- 在地图上显示用户的位置。
- 使用用户的位置标记在您的应用中创建的数据(即为照片添加地理位置标记)。
以负责任的方式请求权限
最近的用户研究表明,用户不信任那些在网页加载时直接提示用户提供其位置的网站。那么,最佳做法是什么呢?
假定用户不将其位置提供给您
许多用户不想将其位置信息提供给您,因此您需要采用防御性开发方式。
- 处理 Geolocation API 中的所有错误,以便您的网站适应这种情况。
- 清晰明确地说明您需要位置信息。
- 请根据需要使用后备解决方案。
在需要地理定位时使用备用方法
我们建议您的网站或应用无需访问用户的当前位置。但是,如果您的网站或应用需要用户的当前位置,可以通过第三方解决方案来推测用户当前所处的位置。
这些解决方案通常会查看用户的 IP 地址,并将其映射到在 RIPE 数据库注册的物理地址。这些位置通常不是非常准确,通常只能提供离用户最近的通讯中心或手机基站的位置。在许多情况下,它们甚至可能没有那么准确,尤其是当用户使用 VPN 或某些其他代理服务时。
始终在手势操作时请求位置信息访问权限
确保用户了解您为何请求其位置,以及这对他们有什么好处。在网站加载首页时立即请求提供位置会导致用户体验不佳。
而应为用户提供明确的号召性用语,或指明某项操作需要访问其位置信息。这样,用户便可以更轻松地将系统访问提示与刚刚发起的操作相关联。
明确指出某项操作会请求获取其位置信息
Google Ads 团队开展的一项研究,要求用户预订波士顿的酒店客房,以参加一个特定酒店网站上即将举行的会议,在点按首页上的“查找和预订”号召性用语后,系统立即提示他们分享自己的 GPS 位置信息。
在某些情况下,用户会感到失望,因为他们不明白为何在想要预订波士顿的客房时,系统显示的却是旧金山的酒店。
确保用户了解您为何要求其提供位置信息,可带来更好的体验。添加在各种设备上通用的熟知的记号,例如测距仪图标,或者添加明确的号召性用语(例如“在我附近查找”)。
温和地请求用户授权访问其位置信息
您无权访问用户所执行的操作。您可以确切知道用户何时禁止访问其营业地点,但您不知道他们何时授予您访问权限;您只有在出现结果时才能知道获得了访问权限。
如果您需要用户完成操作,最好“促使”他们采取行动。
我们建议采用以下做法:
- 设置一个在一小段时间后触发的计时器;5 秒是一个不错的值。
- 如果您收到错误消息,应向用户显示一条消息。
- 如果得到积极回应,则禁用计时器并处理结果。
- 如果在超时后您未收到肯定响应,请向用户显示通知。
- 如果稍后有响应,但通知仍然存在,请将其从屏幕上移除。
button.onclick = function () {
var startPos;
var nudge = document.getElementById('nudge');
var showNudgeBanner = function () {
nudge.style.display = 'block';
};
var hideNudgeBanner = function () {
nudge.style.display = 'none';
};
var nudgeTimeoutId = setTimeout(showNudgeBanner, 5000);
var geoSuccess = function (position) {
hideNudgeBanner();
// We have the location, don't display banner
clearTimeout(nudgeTimeoutId);
// Do magic with location
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
};
var geoError = function (error) {
switch (error.code) {
case error.TIMEOUT:
// The user didn't accept the callout
showNudgeBanner();
break;
}
};
navigator.geolocation.getCurrentPosition(geoSuccess, geoError);
};
浏览器支持
现在,大多数浏览器都支持 Geolocation API,但最好在执行任何操作之前一律检查是否支持。
您可以通过测试是否存在 Geolocation 对象来轻松检查兼容性:
// check for Geolocation support
if (navigator.geolocation) {
console.log('Geolocation is supported!');
} else {
console.log('Geolocation is not supported for this Browser/OS.');
}
确定用户的当前位置
Geolocation API 提供一种简单的“一次性”方法来获取用户的位置信息:getCurrentPosition()
。调用此方法会异步报告用户的当前位置。
window.onload = function () {
var startPos;
var geoSuccess = function (position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
};
navigator.geolocation.getCurrentPosition(geoSuccess);
};
如果这是该网域中的应用首次请求权限,浏览器通常会检查用户是否同意。根据所使用的浏览器,可能还有一些偏好设置始终允许(或禁止)权限查询,在这种情况下,系统会绕过确认流程。
根据浏览器所使用的定位设备,位置对象实际上可能不只包含纬度和经度,还包含许多其他信息;例如,它可能包含海拔高度或方向。在位置系统实际返回数据之前,您无法知道它使用了什么额外信息。
监测用户的位置
借助 Geolocation API,您只需调用 getCurrentPosition()
即可(在征得用户同意的情况下)获取用户的位置。
如果您想持续监控用户的位置,请使用 Geolocation API 方法 watchPosition()
。其运行方式与 getCurrentPosition()
类似,但它会在定位软件出现以下情况时多次触发:
- 更准确地锁定用户。
- 确定用户的位置发生了变化。
var watchId = navigator.geolocation.watchPosition(function (position) {
document.getElementById('currentLat').innerHTML = position.coords.latitude;
document.getElementById('currentLon').innerHTML = position.coords.longitude;
});
何时使用地理定位来监测用户的位置
- 您想更精确地锁定用户位置。
- 您的应用需要根据新的位置信息更新界面。
- 在用户进入某个定义可用区时,您的应用需要更新业务逻辑。
使用地理定位时的最佳实践
始终清理和节省电量
监控地理位置的变化并不是一项自由操作。虽然操作系统可能正在引入平台功能来让应用连接到地理子系统,但作为 Web 开发者,您并不知道用户的设备对监控用户位置有何支持,并且当您观察某个位置时,您会让设备进行大量额外的处理。
如果不再需要跟踪用户位置,请调用 clearWatch
以关闭地理定位系统。
妥善处理错误
遗憾的是,并非所有位置查找都成功。可能是因为 GPS 无法定位,或者用户突然停用了位置信息查找。如果发生错误,系统会调用 getCurrentPosition()
的第二个可选参数,以便您可以在回调内通知用户:
window.onload = function () {
var startPos;
var geoSuccess = function (position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
};
var geoError = function (error) {
console.log('Error occurred. Error code: ' + error.code);
// error.code can be:
// 0: unknown error
// 1: permission denied
// 2: position unavailable (error response from location provider)
// 3: timed out
};
navigator.geolocation.getCurrentPosition(geoSuccess, geoError);
};
减少启动地理定位硬件的必要性
在许多用例中,您不需要用户的最新位置信息;只需粗略的估算值即可。
使用 maximumAge
可选属性,告知浏览器使用最近获取的地理定位结果。如果用户之前请求过数据,这样不仅能更快地返回数据,而且还会阻止浏览器启动其地理定位硬件接口,例如 Wi-Fi 三角测量或 GPS。
window.onload = function () {
var startPos;
var geoOptions = {
maximumAge: 5 * 60 * 1000,
};
var geoSuccess = function (position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
};
var geoError = function (error) {
console.log('Error occurred. Error code: ' + error.code);
// error.code can be:
// 0: unknown error
// 1: permission denied
// 2: position unavailable (error response from location provider)
// 3: timed out
};
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions);
};
设置超时,不让用户持续等待
除非您设置超时,否则您对当前位置的请求可能永远不会返回。
window.onload = function () {
var startPos;
var geoOptions = {
timeout: 10 * 1000,
};
var geoSuccess = function (position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
};
var geoError = function (error) {
console.log('Error occurred. Error code: ' + error.code);
// error.code can be:
// 0: unknown error
// 1: permission denied
// 2: position unavailable (error response from location provider)
// 3: timed out
};
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions);
};
优先使用粗略位置,而不是精确位置
如果您想查找距离用户最近的商店,不太可能需要 1 米的精度。该 API 旨在提供尽快返回的粗略位置。
如果您确实需要较高的精确度,可以使用 enableHighAccuracy
选项替换默认设置。谨慎使用:它的解析速度会比较慢,而且耗电量会增加。
window.onload = function () {
var startPos;
var geoOptions = {
enableHighAccuracy: true,
};
var geoSuccess = function (position) {
startPos = position;
document.getElementById('startLat').innerHTML = startPos.coords.latitude;
document.getElementById('startLon').innerHTML = startPos.coords.longitude;
};
var geoError = function (error) {
console.log('Error occurred. Error code: ' + error.code);
// error.code can be:
// 0: unknown error
// 1: permission denied
// 2: position unavailable (error response from location provider)
// 3: timed out
};
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions);
};
使用 Chrome 开发者工具模拟地理定位
地理位置设置完成后,您需要:
- 测试应用在不同地理位置的运行情况。
- 验证应用在无法使用地理定位时是否以适当方式降级。
您可以通过 Chrome 开发者工具执行这两个操作。
- 打开 Chrome 开发者工具。
- 按 Esc 键打开控制台抽屉。
- 打开控制台抽屉菜单
- 点击传感器选项以显示“传感器”标签页。
在这里,您可以将位置替换为预设的主要城市,输入自定义位置,或通过将替换项设置为位置不可用来停用地理定位。