返回介绍

地理位置(续)

发布于 2025-01-01 12:18:09 字数 7027 浏览 0 评论 0 收藏 0

选择!我需要选择!

有些流行的移动设备——比如 iPhone 和 Android 手机——支持两种方法来找出你在哪里。第一种方法是三角定位法,凭借的是你的手机和与手机交互的运营商的基站的相对位置。这种方法很快速,不需要 GPS 模块,但只能给你一个大致的未知区域。这取决于你所在的区域有多少基站。所以“一块大致的区域”,可能是仅仅是一个城市街区,也可能有一公里的距离。

第二种方法要使用你的设备上的 GPS 模块。GPS 模块与绕地轨道上的 GPS 定位卫星通讯。GPS 通常可以精确到只有几米的位置。这种方法的不足在于 GPS 模块需要消耗大量电力,所以,手机或者其它终端只在需要的时候才开启 GPS 模块。这意味着,启动模块并且等待模块与 GPS 卫星通讯成功都会有一定的延时。

如果你曾经在 iPhone 或者其他智能终端上使用过 Google Map,你应该注意到这两种方法的实际应用。首先你会看到有一个大大的圆圈,显示出你的大概位置(这是由最近的基站找到的),然后是一个较小的圆圈(与其他基站的三角定位),最后是一个点,指出准确的位置(由 GPS 卫星给出)。

我之所以要提到这个问题,在于你的 web 应用程序是否需要如此高得精度。如果你仅仅为了找到附近电影院的列表,“低精度”就足够了。因为不会有很多电影院,即使在大都市中心也不会,并且你也会希望范围尽可能大一点,而不是很小的一个区域。另一方面,如果你需要实时导航,指引方向,显然你应该知道用户的准确位置,于是你就可以说“20 米后右转”之类的提示了。

getCurrentPosition() 函数有第三个可选参数,一个 PositionOptions 对象。这个对象有三个属性,所有属性都是可选的。你可以一个都不设置,也可能全部设置。

PositionOptions 对象属性
属性类型默认值说明
enableHighAccuracyBooleanfalse设置为 true 的话会慢一些
timeoutlong(无)毫秒
maximumAgelong0毫秒

enableHighAccuracy 属性正如其名字一样,使用高精度。如果设置为 true ,并且设备也支持,用户也希望共享他们的准确位置,那么设备就会尝试获取高精度值。iPhones 和 Android 手机对低精度、高精度位置信息都有独立的权限控制,所以,有可能设置了 enableHighAccuracytruegetCurrentPosition() 会失败,但是设置 enableHighAccuracyfalse 的却会成功。

timeout 属性是你的应用程序获取位置信息的一个等待时间,以毫秒为单位。这个计时器在用户同意计算位置之后才会开始倒计时。你并不是对用户计时,而是对网络计时。

maximumAge 属性允许设备使用一个缓存的位置马上应答。例如,你第一次调用 getCurrentPosition() 获取位置信息的时候,用户同意了,你在上午 10:00 的时候成功获取用户的位置信息。一分钟之后,也就是 10:01 的时候,你将 maximumAge 设置为 75000,再一次调用 getCurrentPosition()

navigator.geolocation.getCurrentPosition(
    success_callback,
    error_callback,
    {maximumAge: 75000}
);

此时,你并不太需要用户的当前位置信息,使用一个 75 秒以内的位置就足够了(也就是 75000 毫秒以内任何时刻的位置)。你的设备知道 60 秒之前(60000 毫秒之前)用户的位置,这是刚刚第一次调用 getCurrentPosition() 的获得的。于是,你的设备就不重复计算用户的当前位置了,直接返回第一次获得的结果:相同的经纬度,相同精度,并且是相同的时间戳(上午 10:00)。

在你询问用户位置之前,你应该仔细思考下究竟需要怎样的精度,恰当地设置 enableHighAccuracy 。如果你需要不止一次的获取用户位置,你应该仔细想想有些以前的信息是不是够用了?此时就要恰当地设置 maximumAge 。如果你需要持续不断地获取用户位置信息, getCurrentPosition() 就不适合你,你应该使用 watchPosition() 函数。

watchPosition()getCurrentPosition() 有几乎一样的签名。它也接受两个回调函数,必选的一个用于成功时获得位置信息,可选的一个则用于错误控制。它也接受一个可选的 PositionOptions 对象,能够赋予刚刚我们说过的那些属性值。二者区别在于只要用户位置改变,这个回调函数就会被调用。应用程序没有必要主动拉取其位置。设备自己决定最优的拉取间隔,然后在它认为用户位置发生改变的时候调用你的回调函数。你可以利用这一函数在地图上设置一个标记,提供下一站到哪里,或者其他什么信息。

watchPosition() 函数返回一个数字。你应该将这个数字保存到什么地方。如果你希望停止对用户位置改变的观察,需要调用 clearWatch() 方法,并将这个数字作为参数传给它。设备就会停止调用你的回调函数。如果你曾经使用过 JavaScript 的 setInterval()clearInterval() 函数,就会发现它们是很相像的。

IE 怎么办?

IE9 之前的版本(确切地说是 IE 9.0RC1 之前)并不支持 W3C 的地理位置 API。但是不要失望!Google 提供了一个开源的浏览器插件 Gears 可以解决这个问题。这个插件可以运行于 Windows、Mac、Linux、Windows Mobile 和 Android 上。它可以为老版本浏览器增加新的功能。其中之一就是提供地理位置 API。它的 API 与 W3C 地理位置 API 有些区别,但是目的都是一样的。

现在我们正在处理这些历史遗留问题,我们不得不支持,很多旧的手机浏览器都提供了设备相关的地理位置 API。BlackBerry、Nokia、Palm 和 OMTP BONDI 都提供了自己的 API。当然,这些 API 与 Gears 又不相同,与 W3C 地理位置 API 也不一样。这怎么办呢?

使用 geo.js 解决这个问题

geo.js 是一个使用 MIT 协议开源的 JavaScript 库,用于屏蔽掉 W3C 地理位置 API、Gears API 和 设备相关 API 之间的不同之处。为了使用这个库,我们应该在页面底部添加两个 <script> 标签。(从技术上说,这两个标签放在哪里都可以,但是将其放在 <head> 里面会减缓页面加载,所以不要这么干!)

第一个脚本是 gears_init.js ,用于初始化已经安装了的 Gears。第二个脚本是 geo.js

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Dive Into HTML5</title>
</head>
<body>
    ...
    <script src="gears_init.js"></script>
    <script src="geo.js"></script>
</body>
</html>

现在你可以使用任何能够使用的地理位置 API 了。

if (geo_position_js.init()) {
    geo_position_js.getCurrentPosition(geo_success, geo_error);
}

我们一步步来解释这个问题。首先,你需要调用 init() 函数。如果函数找到一个支持的地理位置 API,则返回 true

if (geo_position_js.init()) {

调用 init() 函数不会真正找到你的位置。仅仅是验证找到位置的可能性。为实际找出位置信息,你应该调用 getCurrentPosition() 函数。

geo_position_js.getCurrentPosition(geo_success, geo_error);

getCurrentPosition() 函数会要求浏览器想你询问是否授权查看和分享你的位置信息。如果地理位置信息由 Gears 给出,将会弹出一个对话框,问你是否信任这个使用了 Gears 的网站。如果浏览器原生支持地理位置 API,对话框就会不同。例如,Firefox 3.5 原生支持地理位置 API。当你尝试使用 Firefox 3.5 获取地理位置时,就会在页面最上方弹出一个信息栏。

getCurrentPosition() 有两个回调函数作为参数。如果 getCurrentPosition() 函数成功找到你的位置——也就是你允许浏览器发现你的位置,并且地理位置 API 也成功了——它会调用作为第一个参数的这个函数。例如,在我们的例子中,成功的回调函数就是 geo_success

geo_position_js.getCurrentPosition(geo_success, geo_error);

成功回调函数有一个参数,保存有位置信息。

function geo_success(p) {
    alert("Found you at latitude "
        + p.coords.latitude
        + ", longitude "
        + p.coords.longitude);
}

如果 getCurrentPosition() 函数找不到你的位置——不管是因为你不允许还是因为地理位置 API 调用失败——它都会调用作为第二个参数的这个函数。在本例中则是 geo_error 。失败的回调函数没有参数:

function geo_error() {
    alert("Could not find you!");
}

geo.js 不支持 watchPosition() 函数。如果你需要持续不断地获取位置信息,只能自己拉取 getCurrentPosition() 的值。

一个完整的实例

下面是一个使用 geo.js 获取你的位置的实例,它会在页面的地图中显示你的实际位置。

它是怎么运作的呢?首先在页面加载的时候,调用了 geo_position_js.init() 来查看地理位置 API 是否可用。如果可用,则点击连接,查找你的位置。这个点击的函数是这样的:

function lookup_location() {
    geo_position_js.getCurrentPosition(show_map, show_map_error);
}

如果你同意发现你的位置,浏览器的后台服务就会去查找你的位置。geo.js 会调用第一个回调函数, show_map() ,这个函数接受一个参数, locloc 对象包含经度、纬度和精度信息。(在本例中没有使用精度信息。) show_map() 函数的其余部分则是调用了 Google Maps API 嵌入一个地图。

function show_map(loc) {
    $("#geo-wrapper").css({'width':'320px','height':'350px'});
    var map = new GMap2(document.getElementById("geo-wrapper"));
    var center = new GLatLng(loc.coords.latitude, loc.coords.longitude);
    map.setCenter(center, 14);
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    map.addOverlay(new GMarker(center, {draggable: false, title: "You are here (more or less)"}));
}

如果 geo.js 不能找到你的位置,则会调用第二个回调函数 show_map_error()

function show_map_error() {
    $("#live-geolocation").html('Unable to determine your location.');
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文