HTML5 定位

Dive into HTML5
HTML5 Geolocation
Geolocation背后的基本原理

HTML定位API用于获取用户的地理位置(经纬度),但由于涉及隐私,除非用户同意,否则我们无法得到用户的位置。

API Chrome IE Firefox Safari Opera
Geolocation 5.0 - 49.0 (http)
50.0 (https)
9.0 3.5 5.0 16.0

从Chrome50开始,定位API只能用于HTTPS的站点,也就是说如果我们的站点不是HTTPS(如HTTP站点),那么获取用户位置的功能无法使用。

使用HTML定位

定位API的使用要围绕全局对象 navigator 的一个新属性 navigator.geolocation 对象(Geolocation 对象)展开,Geolocation 对象有一个获取位置的方法,其定义如下:

1
geolocation.getCurrentPosition(locationSuccess, locationError, options);

getCurrentPosition() 方法可以接受三个参数,locationSuccess和locationError都是函数,分别是定位成功和失败时的回调函数,options是一个 PositionOptions 对象,用来定义定位选项;其中只有第一个参数是必须的,也就是说最简单的使用定位API的代码类似于下面:

1
navigator.geolocation.getCurrentPosition(locationSuccess);

但我们不能这么简单地使用,这段代码里没有定位API支持情况的检测,没有错误处理,也没有定位选项,一般情况下,我们需要包含API支持检测和错误处理才行。

API支持检测可以使用Modernizr

鉴于浏览器支持情况良好,本文不进行定位API支持情况检测

定位成功后,浏览器会调用 getCurrentPosition() 的第一个函数参数,并传入一个 Coordinates参数,该参数对象有两个属性:coords和timestamp,说明如下:

属性 类型 备注
coords.latitude double 定位结果的纬度,十进制小数
coords.longitude double 定位结果的经度,十进制小数
coords.altitude double/null 海拔(米)
coords.accuracy double 定位结果的精确度(米)
coords.altitudeAccuracy double/null 海拔精确度(米)
coords.heading double/null 朝向,偏向正北方顺时针角度
coords.speed double/null 速度(米/秒)
timestamp DOMTimeStamp 定位时间,与Date()结果一样

上面表格中coords对象所有属性只有三个能保证一定有数据:coords.latitude、coords.longitude和coords.accuracy,其它的都有可能为null,这取决于设备的定位能力;另外heading和speed属性是基于用户上次定位的结果来计算的。

处理错误

定位过程是很复杂的,因此容易产生错误,而且用户也不一定会同意我们获取其位置信息,这就要求我们需要对一些无法成功定位的情况进行处理;这时我们就需要关注 getCurrentPosition() 函数的第二个参数了。

如果定位过程产生错误,错误回调函数会被调用并传入一个 PositionError 的对象。

属性 类型 备注
code short 枚举类型的错误代码
message DOMString 错误消息,该信息是用来调试的,不适合给最终用户看

其中code是个枚举类型,其可用的值如下所示:

  • PERMISSION_DENIED(1):用户不允许应用获取其位置信息
  • POSITION_UNAVAILABLE(2):网络不通或定位卫星无法连接
  • TIMEOUT(3):网络通畅但获取位置超时,至于多长时间算超时,定位选项部分会提到

定位选项

一般手机都支持两种定位方式,第一种是通过网络基站计算位置,这不需要GPS参与,因此定位准确度不够,结果的准确性取决于所在区域内基站的数量;另一种方式就是直接使用GPS硬件来定位了,这种方式的精确度可以达到几米范围,但比较耗费电量,因此一般情况下默认会关闭GPS。

getCurrentPosition() 函数的第三个可选参数是一个 PositionOptions 对象,我可以设置三个属性,这三个属性都是可选的,我们可以设置任意一个或全部设置。

属性 类型 默认值 备注
enableHighAccuracy Boolean false 是否启用高精度定位,启用的话可能更慢
timeout long 没有默认值 超时时间(毫秒)
maximumAge long 0 允许使用缓存的时间范围(毫秒),0表示禁用缓存

enableHighAccuracy 属性用来定义是否启用高精度定位,在我们请求用户位置信息前应该先判断我们需要的精度,用该属性去指定;苹果和Android手机都区分低精度和精度定位的权限,因此有可能会产生使用低精度定位成功而使用高精度定位不成功的情况。

timeout 属性定义web应用等待定位的时间,超过该时间不管定位是否成功都将返回,根据情况调用成功或错误回调函数;这里说的等待时间是从用户允许定位开始计时,也就是说我们不是等用户,而是等网络。

maximumAge 属性允许设备使用缓存位置信息立即应答,该属性就是以毫秒为单位定义允许使用多久以前的缓存位置;比如我们在10点时成功定位用户位置,在1分钟后又发起定位请求,maximumAge 属性设置为7500,这时设备就会返回1分钟前的那次定位结果,而不是再次去计算用户当前位置。

其它方法

上面的内容一直都是针对 Geolocation 对象的 getCurrentPosition() 方法来讲解的,其实 Geolocation 对象还有两个其它的方法,它们分别是:

  • watchPosition():连续地请求用户位置信息(跟踪/监视用户位置)
  • clearWatch():停止监视用户位置

watchPosition() 方法的定义与 getCurrentPosition() 方法定义是一样的,不同的是回调函数会一直在用户位置有变化时被调用;我们也不需要主动去轮询用户位置,设备会确定最佳的轮询间隔,并在用户位置变化时调用我们的回调函数。

watchPosition() 方法会返回一个数字,我们应该将数字记下来,并在需要停止监视用户位置时调用 clearWatch() 方法,这个数字就是其参数;调用 clearWatch() 方法后设备就会停止调用回调方法,这与javascript中的 setInterval()clearInterval() 两个方法是一样的。

示例

下面是一个简单的定位示例,但并不能保证总是定位成功,我用Chrome试了下如果翻墙会成功,不翻墙就超时;Firefox不翻墙有时也能成功,其它浏览器没试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function locationSuccess(pos) {
let p = document.getElementById('geo-p');
p.innerHTML = `纬度: ${pos.coords.latitude}<br>经度: ${pos.coords.longitude}`;
}
function locationError(error) {
console.log(error.code + ':' + error.message);
}
(function () {
document.getElementById('get-location-btn').addEventListener('click', function(e) {
navigator.geolocation.getCurrentPosition(locationSuccess, locationError, {
enableHighAccuracy: true,
timeout: 3000
});
});
})();

 

接下来是一个结合高德地图的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function () {
let map = new AMap.Map('map-container',{
zoom: 15,
center: [116.39, 39.9]
});
function locationSuccess(pos) {
map.panTo(new AMap.LngLat(pos.coords.longitude, pos.coords.latitude));
var marker = new AMap.Marker({
map : map
});
}
function locationError(error) {
console.log(error.code + ':' + error.message);
}
navigator.geolocation.getCurrentPosition(locationSuccess, locationError, {
enableHighAccuracy: true,
timeout: 5000
});
})();
文章目录
  1. 1. 使用HTML定位
  2. 2. 处理错误
  3. 3. 定位选项
  4. 4. 其它方法
  5. 5. 示例
|