首页 HTML5 Dive Into HTML5:地理位置

Dive Into HTML5:地理位置

0 1.7K

地理位置可以找到你在这个世界上的位置,如果你愿意,还可以将这个信息分享给你的朋友。我们有很多种方法来找出你所在的位置:IP 地址,无线网络的连接(我们可以根据你的手机连接到哪个基站来识别出位置),或者是设备中的 GPS 模块。

Q: 地理位置听起来很恐怖,我可以关闭吗?

A: 与远程服务器共享你的物理位置的确是一件涉及隐私的问题。地理位置 API 明确要求:“User Agent 不能够在不经用户允许的情况下发送位置信息。”换句话说,分享你的位置是可选的。如果你不愿意,不要分享就好了。

地理位置 API

地理位置 API 可以让你同信任的网站分享位置信息。页面的 JavaScript 可以获取纬度和经度信息,这些信息可以发送到远程服务器上,以便完成一些与位置相关的操作,比如本地商业信息或者在地图上显示你的位置等。

下面的表格显示,地理位置 API 在绝大多数桌面和手机浏览器上都可以使用。另外,老版本的浏览器或设备也可以使用第三方库来实现类似的功能,这一点我们会在后面详细讲述。

IEFirefoxSafariChromeOperaiPhoneAndroid
9.0+3.5+5.0+5.0+10.6+3.0+2.0+

除了支持标准的地理位置 API,一些移动设备还支持某些特殊的 API。我们在后面的内容中也会对此有所阐述。

从代码说起

地理位置 API 会在全局navigator对象增加一个新的属性:navigator.geolocation。使用 API 最简单的代码类似这样:

function get_location() {
    navigator.geolocation.getCurrentPosition(show_map);
}

我们的代码没有检测信息,没有错误处理,没有各种选项。正式的 web 程序至少应该包含这里所说的前两个。为了检测地理位置 API,我们可以使用 Modernizr:

function get_location() {
    if (Modernizr.geolocation) {
        navigator.geolocation.getCurrentPosition(show_map);
    } else {
        // no native support; maybe try Gears?
    }
}

你自己要决定,如果地理位置不能使用该怎么办。一会儿我们将解释 Gears 的 fallback 选项,但现在我们先来说说在调用getCurrentPosition()的时候究竟会发生什么。就像我们前面所说的,地理位置是可选的。这意味着浏览器不会强制向服务器发送你的当前物理位置。不同浏览器的处理是不一样的。在 Mozilla Firefox 中,调用getCurrentPosition()函数将在浏览器窗口顶部弹出提示栏,类似下面的截图:

我们来解释一下这个提示。作为一个最终用户,这个提示会告诉你这几个信息:

  • 有网站想要你的位置信息;
  • 哪个网站想要你的位置信息;
  • “了解更多…” 是 Mozilla 的帮助页面,这个页面会解释下面将会发生什么(小故事:Google 会按照其 Location Service Privacy Policy 提供和存储你的数据);
  • 可以选择分享你的位置;
  • 可以选择不分享你的位置;
  • 可以选择“永远共享”,“永不共享”和“暂不”

另外,这个提示:

  • 非模态的,所以你不必担心不能切换到其他窗口或标签页;
  • 独立于标签页,因此当你切换浏览器窗口或标签页的时候,这个标记将会消失,切换回来的时候又会出现;
  • 不可控的,所以没有办法绕过
  • 阻塞的,因此只要你不做出选择,网站就不能做出任何操作。

刚刚见到的是使用 JavaScript 代码显示这个提示框。这是一个简单的函数调用,接受一个回调函数(这里我们的回调函数就是show_map)。getCurrentPosition()的调用会立即返回,但是这并不意味着你马上可以访问用户位置信息。你第一次能够获得位置信息的地方是在这个回调函数里面。回调函数看上去是这样子的:

function show_map(position) {
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
    // let's show a map or do something interesting!
}

回调函数接受一个参数,这是一个有两个属性的对象:coordstimestamptimestamp是计算出来位置信息的时刻。(因为这个过程是异步的,我们不能知道究竟是什么时候获得的这个数据。用户阅读这个提示框,以及他们同意共享位置都需要一定的时间。带有 GPS 模块的设备也需要一段时间去连接 GPS 卫星。)coords有像latitudelongitude这样的属性,用来给出用户的物理位置信息。

position 对象
属性类型说明
coords.latitudedouble纬度:十进制浮点数,单位-度
coords.longitudedouble经度:十进制浮点数,单位-度
coords.altitudedouble 或 null海拔:高于参考椭球,单位-米
coords.accuracydouble精度:单位-米
coords.altitudeAccuracydouble 或 null海拔精度:单位-米
coords.headingdouble 或 null与正北方向的偏移角度:顺时针方向,单位-度
coords.speeddouble 或 null移动速度:单位-米/秒
timestampDOMTimeStamp同 Date() 一样

只有三个属性是必须要有值的:coords.latitudecoords.longitudecoords.accuracy。其余的可能是null,这取决于你的设备和后端位置服务器的能力。如果有的话,headingspeed属性则要根据你先前的位置计算出来。

处理错误

地理位置很复杂,可能会出错。我们曾经提到过要求“用户同意”。如果你的程序需要用户位置信息,但是用户却不同意,那你就郁闷了。用户选择肯定要放在第一位。那么我们的代码怎么写呢?这就用到了getCurrentPosition()的第二个参数:错误处理的回调函数:

navigator.geolocation.getCurrentPosition(show_map, handle_error)

如果有什么出错了,这个错误处理函数就会被调用,其参数是PositionError对象。

PositionError 对象
属性类型说明
codeshort枚举类型
messageDOMString对最终用户而言是不友好的

其中,code是枚举类型,其值为:

  • PERMISSION_DENIED(1):用户点击“不要共享”按钮,或者有其他原因无法获取位置信息;
  • POSITION_UNAVAILABLE(2):网络错误,或者无法连接到卫星;
  • TIMEOUT(3):网络是畅通的,但是花费很长时间计算用户位置。多长算“很长”?我们以后会详细解释这个问题。
  • UNKNOWN_ERROR(0):其他错误。
function handle_error(err) {
    if (err.code == 1) {
        // user said no!
    }
}

Q: 地理位置 API 可以在国际空间站上使用吗?可以在月球上或者其他星球上用吗?

A: 地理位置标准是这样阐述的:“地理坐标参考系的属性值来自大地测量系统(World Geodetic System (2d) [WGS84])。不支持其他参考系。”国际空间站位于地球轨道上,所以宇航员可以使用经纬度和海拔来描述其位置。但是,大地测量系统是以地球为中心的,因此也就不能使用这个系统来描述月球或者其他星球的位置了。

发表评论

关于我

devbean

devbean

豆子,生于山东,定居南京。毕业于山东大学软件工程专业。软件工程师,主要关注于 Qt、Angular 等界面技术。

主题 Salodad 由 PenciDesign 提供 | 静态文件存储由又拍云存储提供 | 苏ICP备13027999号-2