地理定位
地理定位这个术语恰当地描述了确定一个人、一个地点或一个东西所在地理位置的概念。尽管在现在看来,使用内置GPS的设备确定我们的位置既容易页方便,但过去却不是这样。过去的人们从使用烟雾信号开始,到人类发明出可以精确地确定自己所在位置的技术经历了漫长的发展过程。
你的位置就是地图上的一个点。这个点涉及两方面信息:纬度和经度,GPS软件根据它们来确定你的位置。既然有了一个点,那应用就可以通过反向地理编码的过程来取得用户周围地区的信息。
地理编码是一种为相关文本信息(如街道地址、邮政编码)标注地理坐标的方法。反向地理编码是一个相反的过程,即基于地理坐标来使用相关的文本位置信息。
现在的计算设备可以通过多种方法获得位置信息,并不是所有设备都依赖于GPS卫星。以下是几种处理位置信息的方法:
- GPS
- IP地址
- GSM/CDMA Cell ID
- Wi-Fi和蓝牙的MAC地址
- 用户输入
坐标系统
在地理坐标系中,坐标由经度、纬度和海拔高度来表示。
球体上的水平线是纬线,南北两个半球的纬度从赤道开始向两级递增,最大为90度。球体上的垂直线是经线,以本出子午线为起点,东西半球的经线各划分为180度。
1. 十进制度数与度分秒
在定位地球上某一点时,为了达到必要的精度,经纬度实际会被分成度(°)、分(′)和秒(″)。1分等于60秒,1度等于60分。
在以度数表示的坐标中,经常能够看到如下形式:
- 度、分、秒 (及秒的小数部分)
- 度、分(及分的小数部分)
- 十进制度数
2. DMS到十进制度数的转换
把DMS坐标转换成十进制度数很直观,只要按照如下步骤做即可。
- 计算总秒数
- 用这个总秒数除以3600(每度的秒数)
- 将得到的小数添加整数度数后面
- 如果坐标是南纬或西经,则为结果加上负号
3. 十进制度数到DMS的转换
从十进制度数坐标转换到DMS坐标也很直观,只要按照下面步骤做即可。
- 从整个坐标值中减去整数,得到小数
- 用小数乘以60(得到分)
- 从整个分的值中减去整数,得到小数
- 用小数乘以60(得到秒)
- 如果十进制坐标是负的经度值,那么保留整数度数的符号,或去掉符号并加上一个W;否则,加上一个E。如果十进制坐标是负的纬度值,那么保留整数度数的符号,或去掉符号并加上一个S;否则,加上一个N。
W3C Geolocation API
W3C Geolocation API 是一个规范,规定了如何使用脚本访问主机设备的地理位置信息。这个规范的目的是提供一套“高层次接口”,让开发人员无需知道如何确定位置信息即可使用它们。有了这套API,设备在地理定位时是使用GPS、IP地址,还是Cell ID都不重要了,重要的只有地理定位信息本身。但是,这个规范也有一个问题,即它不保证API返回的位置信息事设备的真实位置。
API的支持情况
Web浏览器 | 支持的版本 |
---|---|
Firefox | 3.5+ |
Chrome | 5.0+ |
IE | 9.0+ |
Safari | 5.0+ |
Opera | 10.6+ |
iPhone | 3.1+ |
Android | 2.0+ |
BlackBerry | 6+ |
Geolocation对象
有一个对象持有W3C Geolocation API的全部实现,它就是Geolocation对象。在JavaScript中,可以使用Geolocation对象来获取浏览器所在设备的地理定位信息。Geolocation对象是浏览器对象window.navigator
的一个新属性,可以这样来访问它的实例:window.navigator.geolocation。
与使用其他JavaScript对象一样,使用Geolocation对象之前,最好先测试一下浏览器是否实现了这个对象,如下所示:
if(window.navigator.geolocation) {
// 地理定位操作
} else {
// 浏览器本机不支持地理定位
}
这段代码测试了geolocation属性的实现是否存在。如果存在,则执行某些地理定位操作,否则就尝试执行其他操作。
Geolocation对象有三个公有方法。通过使用这几个方法,可以实现任何地理定位功能。
方法 | 说明 |
---|---|
clearWatch(watchId) | 停止监视传入的watchId的相关进程 |
getCurrentPosition(successCallback, [errorCallback, [options]]) | 尝试取得地理定位信息,成功则调用successCallback,失败则调用errorCallback(可选) |
watchPosition(successCallback, [errorCallback, [options]]) | 尝试以固定的时间间隔取得地理定位信息,成功则调用successCallback,失败则调用errorCallback(可选) |
getCurrentPosition()
在验证了浏览器支持W3C Geolocation API之后,就可以发送请求来取得当前设备所在的位置了。为此,需要使用getCurrentPosition()方法。
if(window.navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options);
} else {
alert("Your browser does not natively support geolocation");
}
function successCallback(position) {
// 使用位置信息做些什么
}
function errorCallback(position) {
// 取得位置信息时遇到了问题
}
PositionOptions对象
PositionOptions对象是一个可选的参数,可以将其传递到getCurrentPosition()方法,也可以传递到watchPosition()方法中去。
方法 | JavaScript类型 | 说明 |
---|---|---|
enableHighAccuracy | Boolean | 标志,告诉API尽可能取得与设备实际位置最接近的位置信息。默认值为false。如果把这个属性设置为true,有可能延长响应时间或者增加电量消耗 |
maximumAge | Integer | 表示应用可以接受缓存的位置信息,但缓存的时间不能超过指定的毫秒数。默认值为0 |
timeout | Integer | 表示应用从一次调用开始到successCallback函数被调用最长会等待多长时间,以毫秒表示。默认值为0 |
下面是一个实例:
var options = {
enableHighAccuracy: true,
maximumAge: 60000,
timeout: 4500
};
navigator.geolocation(successCallback, errorCallback, options);
如果你每次都想得到最新的位置信息,就不要设置maximumAge属性(其默认值为0),或者显式地将其设置为0。如果你每次都想得到缓存的位置信息,那么在调用相应的方法时,将这个属性设置为Infinity。
watchPosition()
watchPosition()方法被调用的时候会返回一个值,这个值用来唯一地标识该监视操作。监视操作本身是异步操作。一下是调用该方法的实例:
var watcher = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
以下代码片段展示了如何使用watchPosition()方法:
var watcher = null;
var options = {
enabelHighAccuracy: true,
timeout: 45000
};
if(window.navigator.geolocation) {
watcher = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
} else {
alert("Your browser does not natively support geolocation");
}
function successCallback() {
// 使用位置信息做些什么
}
function errorCallback() {
// 取得位置信息时遇到了问题
}
watchPosition()方法内置有自动轮询功能,可以检测设备的位置是否改变,每次轮询得到设备的新位置,都会调用successCallback()函数。这样,开发人员就不必自己编写代码每过多少秒去轮询一次设备了。
只要可能,都应该使用watchPosition()方法的自动轮询能力来更新位置。除非你的应用特别需要,否则都不要自己编写代码实现轮询定位。
clearWatch()
W3C Geolocation API提供的clearWatch()方法,传入想要清除的watchId,就可以清除相应的监视操作。这个方法的语法如下:
navigator.geolocation.clearWatch(watcher);
下面代码展示了如何创建一次新的监视操作,然后在成功取得位置信息后撤销该监视:
var watcher = null;
var options = {
enabelHighAccuracy: true,
timeout: 45000
};
if(window.navigator.geolocation) {
watcher = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
} else {
alert("Your browser does not natively support geolocation");
}
function successCallback() {
navigator.geolocation.clearWatch(watcher);
}
Position对象
Position对象中保存着W3C Geolocation API调用返回的所有地理定位信息,这个对象将被传递给successCallback函数。
Position对象的属性
属性 | 说明 |
---|---|
coords | Coordinates对象,包含地理坐标和其他属性 |
timestamp | DOMTimeStamp对象,保存着获取Position对象的时间 |
通过API取得主要地理信息都保存在一个Coordinates对象中,这个对象是Position对象的属性。
Coordinates对象的属性
属性 | 说明 |
---|---|
latitude | 设备的地理坐标纬度,以十进制度数表示 |
longitude | 设备的地理坐标经度,以十进制度数表示 |
altitude | 设备的地理海拔高度 |
accuracy | 经、纬度坐标的精度,以米表示 |
altitudeAccuracy | 海拔高度的精度,以米表示。此属性值为null,表示未被支持 |
heading | 设备移动的方向,以从0°~360°之间的度数表示。 |
speed | 设备当前的地面移动速度,以米每秒表示。此属性值为null,表示未被支持 |
PositionError对象
PositionError对象中保存了W3C Geolocation API调用返回的所有错误信息,这个对象将被传递给errorCallback函数。
隐私问题
为了解决与W3C Geolocation API相关的安全及隐私问题,该规范规定在未得到用户明确授权的情况下,不得将位置信息发送到web应用。所有浏览器遵循这一规定的标准实现方式,就是提供一个信息栏并按照规范显示请求位置文档的URI。
用户允许应用在特定浏览器中具有站点级的访问权限后,该许可会在当前浏览器会话结束时失效。