用户位置

借助 Geolocation API,您可以在征得用户同意的情况下发现用户的位置信息。

借助 Geolocation API,您可以在征得用户同意的情况下获取用户的位置信息。您可以使用此功能来引导用户前往目的地,以及为用户创建的内容添加地理位置标记;例如,标记照片的拍摄地点。

借助 Geolocation API,您还可以查看用户所在的位置,并在用户移动时密切关注他们(始终征得用户同意,并且仅在网页处于打开状态时)。这会产生许多有趣的用例,例如与后端系统集成,以便在用户在附近时准备好订单以供自提。

使用 Geolocation API 时,您需要注意很多事项。本指南将向您介绍常见的用例和解决方案。

摘要

  • 在对用户有益时使用地理定位。
  • 以明确响应用户手势的方式请求权限。
  • 使用功能检测,以防用户的浏览器不支持地理定位。
  • 不要仅了解如何实现地理位置信息;还要了解使用地理位置信息的最佳方式。
  • 使用您的网站测试地理位置信息。

何时使用地理定位

  • 查找用户距离特定实际位置最近的位置,以量身定制用户体验。
  • 根据用户所在的位置量身定制信息(例如新闻)。
  • 在地图上显示用户的位置。
  • 使用用户的位置信息标记在应用中创建的数据(即为照片添加地理标记)。

以负责任的方式请求权限

近期的用户研究表明,用户不信任仅在网页加载时提示用户提供其位置的网站。那么,最佳实践是什么?

假设用户不会向您提供其位置信息

许多用户不愿意向您提供其位置信息,因此您需要采用防御性开发方式。

  1. 处理 Geolocation API 中的所有错误,以便您根据这种情况调整网站。
  2. 明确说明您对相应位置信息的需求。
  3. 如有必要,请使用后备解决方案。

如果需要地理定位,请使用后备方案

我们建议您的网站或应用不要要求访问用户的当前位置信息。不过,如果您的网站或应用需要用户的当前位置信息,您可以使用第三方解决方案来尽可能推断出用户当前所在的位置。

这些解决方案通常的工作原理是查看用户的 IP 地址,并将其映射到在 RIPE 数据库中注册的物理地址。这些位置通常不太准确,通常会显示距离用户最近的通信枢纽或手机信号塔的位置。在许多情况下,这些信息可能并不准确,尤其是当用户使用 VPN 或其他代理服务时。

在用户执行手势时始终请求位置信息访问权限

请务必让用户了解您请求其位置信息的原因,以及这对他们有什么好处。如果在网站加载时立即在首页上请求用户提供信息,会导致用户体验不佳。

在实体店查找工具页面上请求权限的网站。
正确做法:始终在用户执行手势时请求访问位置信息。
在首页上请求权限的网站。
不建议:在网站加载时在首页上请求用户提供信息;这会导致用户体验不佳。

相反,请向用户提供明确的号召性用语,或指明某项操作需要访问其位置信息。这样,用户就可以更轻松地将请求访问权限的系统提示与刚刚发起的操作相关联。

明确说明某项操作会请求用户的位置信息

根据 Google Ads 团队的一项研究,当用户被要求在某个特定酒店网站上预订波士顿的酒店客房以参加即将举行的会议时,他们在点按首页上的“查找和预订”号召性用语后,系统会立即提示他们分享 GPS 位置信息。

在某些情况下,用户会感到沮丧,因为他们不明白为什么在想要预订波士顿的客房时,系统会向他们显示旧金山的酒店。

为了提供更好的体验,请确保用户了解您请求其位置信息的原因。添加在各个设备上通用的知名标志(例如测距仪),或添加明确的号召性用语(例如“查找附近的酒店”)。

测距仪。
使用测距仪
包含“查找我附近的取款机”按钮的表单。
用于查找附近商家的具体号召性用语

温和地提示用户授予位置信息权限

您无权访问用户的任何活动。您可以确切知道用户何时禁止您访问其位置信息,但不知道用户何时授予您访问权限;只有在结果显示时,您才知道自己获得了访问权限。

如果您需要用户执行操作,最好“促使用户”执行操作。

我们建议采用以下做法:

  1. 设置一个在短时间后触发的计时器;5 秒是一个不错的值。
  2. 如果您收到错误消息,请向用户显示消息。
  3. 如果您收到肯定的回复,请停用计时器并处理结果。
  4. 如果在超时后,您未收到正面响应,请向用户显示通知。
  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,但最好在执行任何操作之前先检查是否支持。

您可以通过测试地理位置对象是否存在来轻松检查兼容性:

// 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() 类似,但会随着定位软件而多次触发:

  1. 获取对用户更准确的锁定。
  2. 确定用户的位置正在变化。
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 开发者工具中执行这两项操作。

  1. 打开 Chrome 开发者工具
  2. Esc打开控制台抽屉
  3. 打开控制台抽屉菜单
  4. 点击 Sensors 选项以显示“Sensors”标签页。

在这里,您可以将位置替换为预设的主要城市、输入自定义位置,或将替换项设置为位置信息不可用以停用地理定位。

反馈