H5之地理位置必知必会
【02】概念
规范地址:http://www.w3.org/TR/geolocation-API/
HTML5 Geolocation(地理定位)用于定位用户的位置。
定位用户的位置HTML5 Geolocation API 用于获得用户的地理位置。鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的。
HTML5 Geolocation API 允许我们对喜欢的网站共享我们的位置。JavaScript 可以捕获到纬度和经度,还可以发送给后端服务器,然后做一些位置感知的事情,比如查找本地企业或者在地图上显示我们的位置。
【】严格来说,Geolocation API并不属于HTML5标准规范,但其API接口使得它能让浏览器或者移动设备的浏览器获取用户的当前位置信息。
由于地理定位涉及用户个人隐私信息,因此在任何时候第一次使用Geolocation地理定位功能的页面,都需要用户确认是否允许Web应用程序获取自己的位置信息。
图7-1显示了在iPhone的Safari浏览器下,用户第一次使用地理定位功能时,默认提示用户是否接受浏览器的获取地理位置信息。
总的来说,在PC的浏览器中 HTML5 的地理位置功能获取的位置精度不够高,如果借助这个 HTML5 特性做一个城市天气预报是绰绰有余,但如果是做一个地图应用,那误差还是太大了。
不过,如果是移动设备上的 HTML5 应用,可以通过设置 enableHighAcuracy 参数为 true,调用设备的 GPS 定位来获取高精度的地理位置信息。
Geolocation API(地理位置API)
用途:
1. Geolocation API的应用
Geolocation API能够将用户所在地理位置信息发送给用户许可的站点,而站点可以利用这些信息为用户提供位置相关的服务,例如显示用户位置、寻找周边商家、导航行车路线等。
2. 地理位置的获取方式
获取地理位置的方式有很多种,虽然因获取方式的工作原理不同,它们有非常明显的精度差异,但是在实际工作环境中,又有各自的优点和不足。
IP地址
这是一种比较不准确地获取地理位置的办法,很多时候获取的是ISP机房的位置,但是获取非常方便,没有什么限制。大多数时候,IP地址还是比较准确的,基本上能精确到某个小区或某个大楼,但是如果用户使用代理或者VPN,就可能导致非常大的偏差。
GPS
这是一种非常准确地获取地理位置的方法,GPS的精度可以达到10米左右。如果用来找人或者找建筑,基本上都在目视范围内。但是使用GPS还有一些限制:在室内使用时,信号不太稳定,搜索卫星的时间较长,会造成延时。使用GPS最大的障碍是:很多设备(比如笔记本电脑)基本上都不带GPS,而只有智能手机才有。
Wi-Fi基站
连接位置已知的公共Wi-Fi时,可以获得地理位置信息。这种定位的精度比较不错,而且还可以在室内定位。不过由于位置公开的Wi-Fi比较少,此种方法的适用范围比较少。从目前的各类科技新闻来看,北京、上海、广州将率先建立公共Wi-Fi基站,北京甚至在公交车上都已经设立Wi-Fi基站,这些也可以考虑到未来的应用中。
GSM或CDMA基站
通过电话局基站定位,定位精度随基站密度变化,精度非常一般,而且只有手机才能使用,并且地理位置信息往往不太精确。
综上所述,Geolocation API在移动设备上比较实用,而在个人电脑上常用于电子地图查询。
3. 地理位置获取流程
由于地理位置信息涉及个人隐私,是受到法律保护的,因此,每当用户在使用地理位置信息时,提供地理位置获取服务的软件都应该遵守地理位置获取的技术流程,经由用户同意,才可以获取信息。在桌面浏览器上,此技术流程大致如下(在移动设备非浏览器环境下会略有差异):
(1) 用户打开需要获取地理位置的Web应用;
(2) 应用向浏览器请求地理位置,浏览器弹出询问窗口,询问用户是否共享地理位置;
(3) 假设用户允许,浏览器从设备查询相关信息;
(4) 浏览器将相关信息发送到一个信任的位置服务器,服务器返回具体的地理位置。
【02】语法
地理定位 APIs 是作为全局 navigator 对象的一个新属性工作的。可以按照如下方式创建地理定位对象:
var geolocation = navigator.geolocation;
地理对象是一个允许组件检索设备地理位置相关信息的服务对象。
此属性指代一个拥有如下这三个方法的对象:
navigator.geolocation.getCurrentPosition()
获取用户当前位置。
navigator.geolocation.watchPosition()
获取当前位置,同时不断地监视当前位置,一旦用户位置发生更改,就会调用指定的回调函数。
navigator.geolocation.clearWatch()
停止监视用户位置。传递给此方法的参数应当是调用watchPosition()方法获得的返回值。
如下代码展示了一个获取位置的简单例子:
navigator.geolocation.getCurrentPosition(function(pos) {
var latitude = pos.coords.latitude;
var longitude = pos.coords.longitude;
alert("Your position: " + latitude + ", " + longitude);
});
除了经度和纬度外,凡是成功获取到的地理位置信息还包括一个精度值(米为单位),该值表示获取到的位置信息精度是多少。
浏览器支持
Internet Explorer 9、Firefox、Chrome、Safari 以及 Opera 支持地理定位。注释:对于拥有 GPS 的设备,比如 iPhone,地理定位更加精确。
【05】检测浏览器是否支持Geolocation API
检测浏览器是否支持Geolocation API
Geolocation API在浏览器上的能力检测代码如下:
if(navigator.geolocation){
//你的浏览器支持Geolocation API
} else{
//你的浏览器不支持Geolocation API
}
【】如何使用Geolocation API
Geolocation API是通过window.navigator.geolocation获得对地理定位的访问的。
该对象有如下三个方法:
方法 | 描述 |
---|---|
getCurrentPosition() |
这个方法用于检索用户的当前地理位置。 |
watchPosition() |
这个方法用于检索设备当前地理位置定期更新信息。 |
clearWatch() |
这个方法用于取消 watchPosition 方法调用。 |
示例
下面是一个使用上述方法的示例代码:
functiongetLocation(){
var geolocation = navigator.geolocation;
geolocation.getCurrentPosition(showLocation, errorHandler);
}
这里的 showLocation 和 errorHandler 分别是用来获取实际位置和处理错误的回调方法。
监视移动设备的位置变化
watchPosition和clearWatch是一对方法,其原理和setInterval、setTimeout方法相同。watchPosition方法会返回一个唯一标识,clearWatch可通过这个唯一标识清除watchPosition方法的监听。
watchPosition的语法和getCurrentPosition相同,可以传入三个参数,分别是
● 第一个参数是监听成功后返回的函数;(必选)
● 第二个参数是监听失败时返回的函数;(可选)该函数会传递一个参数到函数内部,该参数记录着返回的错误信息。
● 第三个参数(可选)指定了是否需要高精度的位置信息,该位置信息的过期时间,以及允许系统在多长时间内获取位置信息。
【】watchPosition()
– 返回用户的当前位置,并继续返回用户移动时的更新位置(就像汽车上的 GPS)。
使用watchPosition()时,可以持续获取地理位置信息,浏览器多次调用updateLocation()函数以便传递最新的位置。该函数返回一个watchID,使用navigator.geolocation.clearWatch(watchId)可以清除此updateLocation()函数的回调,使用不带参数的navigator。
【】geolocation.clearWatch()
– 停止 watchPosition() 方法。
可以清除watchPosition()方法信息。
下面的例子展示 watchPosition() 方法。您需要一台精确的 GPS 设备来测试该例(比如 iPhone):
实例
<script>
var x=document.getElementById("demo");
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.watchPosition(showPosition);
}
else{x.innerHTML="Geolocation is not supported by this browser.";}
}
function showPosition(position)
{
x.innerHTML="Latitude: " + position.coords.latitude +
"<br />Longitude: " + position.coords.longitude;
}
</script>
示例
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>moyu's demo</title>
</head>
<body>
<script type="text/javascript">
navigator.geolocation.getCurrentPosition(function(pos){
console.log("当前地理位置的纬度: "+pos.coords.latitude);
console.log("当前地理位置的经度: "+pos.coords.longitude);
console.log("当前地理位置的精度: "+pos.coords.accuracy);
});
var watchID = navigator.geolocation.watchPosition(function(pos){
console.log("当前位置变化的纬度: "+pos.coords.latitude);
console.log("当前位置变化的经度: "+pos.coords.longitude);
console.log("当前位置变化的精度: "+pos.coords.accuracy);
navigator.geolocation.clearWatch(watchID);
},function(){});
</script>
</body>
</html>
**
【02】getCurrentPosition()
Description
The getCurrentPosition method retrieves the current geographic location of the device. The location is expressed as a set of geographic coordinates together with information about heading and speed. The location information is returned in a Position object.
Syntax
Here is the syntax of this method −
getCurrentPosition(showLocation, ErrorHandler, options);
Parameters
Here is the detail of parameters −
showLocation − This specifies the callback method that retrieves the location information. This method is called asynchronously with an object corresponding to the Position object which stores the returned location information.
ErrorHandler − This optional parameter specifies the callback method that is invoked when an error occurs in processing the asynchronous call. This method is called with the PositionError object that stores the returned error information.
options − This optional parameter specifies a set of options for retrieving the location information. You can specify (a) Accuracy of the returned location information (b) Timeout for retrieving the location information and (c) Use of cached location information.
Return value
The getCurrentPosition method does not return a value.
<!DOCTYPE HTML>
<html>
<head>
<script type = "text/javascript">
function showLocation(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
alert("Latitude : " + latitude + " Longitude: " + longitude);
}
function errorHandler(err) {
if(err.code == 1) {
alert("Error: Access is denied!");
} else if( err.code == 2) {
alert("Error: Position is unavailable!");
}
}
function getLocation() {
if(navigator.geolocation) {
// timeout at 60000 milliseconds (60 seconds)
var options = {timeout:60000};
navigator.geolocation.getCurrentPosition(showLocation, errorHandler, options);
} else {
alert("Sorry, browser does not support geolocation!");
}
}
</script>
</head>
<body>
<form>
<input type = "button" onclick = "getLocation();" value = "Get Location"/>
</form>
</body>
</html>
**
【03】watchPosition()
如果你希望跟踪用户的位置,那么可以使用另一个方法watchPosition()
。这个方法接收的参数与getCurrentPosition()
方法完全相同。实际上,watchPosition()
与定时调用getCurrentPosition()
的效果相同。在第一次调用watchPosition()
方法后,会取得当前位置,执行成功回调或者错误回调。
然后,watchPosition()
就地等待系统发出位置已改变的信号(它不会自己轮询位置)。
调用watchPosition()
会返回一个数值标识符,用于跟踪监控的操作。基于这个返回值可以取消监控操作,只要将其传递给clearWatch()
方法即可(与使用setTimeout()
和clearTimeout()
类似)。
例如:
var watchId = navigator.geolocation.watchPosition(function(position){
drawMapCenteredAt(position.coords.latitude, positions.coords.longitude);
}, function(error){
console.log("Error code: " + error.code);
console.log("Error message: " + error.message);
});
clearWatch(watchId);
以上例子调用了watchPosition()
方法,将返回的标识符保存在了watchId
中。然后,又将watchId
传给了clearWatch()
,取消了监控操作。
Description
The watchPosition method retrieves periodic updates about the current geographic location of the device. The location is expressed as a set of geographic coordinates together with information about heading and speed.
The location information is returned in a Position object. Each update returns a new Position object.
Syntax
Here is the syntax of this method −
watchPosition(showLocation, ErrorHandler, options);
Parameters
Here is the detail of parameters −
showLocation − This specifies the callback method that retrieves the location information. This method is called asynchronously with an object corresponding to the Position object which stores the returned location information.
ErrorHandler − This optional paramter specifies the callback method that is invoked when an error occurs in processing the asynchronous call. This method is called with the PositionError object that stores the returned error information.
options − This optional paramter specifies a set of options for retrieving the location information. You can specify (a) Accuracy of the returned location information (b) Timeout for retrieving the location information and (c) Use of cached location information .
Return value
The watchPosition method returns a unique transaction ID (number) associated with the asynchronous call. Use this ID to cancel the watchPosition call and to stop receiving location updates.
Example
<!DOCTYPE HTML><head><html><scripttype="text/javascript">var watchID;var geoLoc;functionshowLocation(position){var latitude = position.coords.latitude;var longitude = position.coords.longitude;
alert("Latitude : "+ latitude +" Longitude: "+ longitude);}functionerrorHandler(err){if(err.code ==1){
alert("Error: Access is denied!");}elseif( err.code ==2){
alert("Error: Position is unavailable!");}}functiongetLocationUpdate(){if(navigator.geolocation){// timeout at 60000 milliseconds (60 seconds)var options ={timeout:60000};
geoLoc = navigator.geolocation;
watchID = geoLoc.watchPosition(showLocation, errorHandler, options);}else{
alert("Sorry, browser does not support geolocation!");}}</script></head><body><form><inputtype="button"onclick="getLocationUpdate();"value="Watch Update"/></form></body></html>
**
【04】clearWatch()
Description
The clearWatch method cancels an ongoing watchPosition call. When cancelled, the watchPosition call stops retrieving updates about the current geographic location of the device.
Syntax
Here is the syntax of this method −
clearWatch(watchId);
Parameters
Here is the detail of parameters −
watchId − This specifies the unique ID of the watchPosition call to cancel. The ID is returned by the watchPosition call.
Return value
The clearWatch method does not return a value.
Example
<!DOCTYPE HTML><html><head><scripttype="text/javascript">var watchID;var geoLoc;functionshowLocation(position){var latitude = position.coords.latitude;var longitude = position.coords.longitude;
alert("Latitude : "+ latitude +" Longitude: "+ longitude);}functionerrorHandler(err){if(err.code ==1){
alert("Error: Access is denied!");}elseif( err.code ==2){
alert("Error: Position is unavailable!");}}functiongetLocationUpdate(){if(navigator.geolocation){// timeout at 60000 milliseconds (60 seconds)var options ={timeout:60000};
geoLoc = navigator.geolocation;
watchID = geoLoc.watchPosition(showLocation, errorHandler, options);}else{
alert("Sorry, browser does not support geolocation!");}}functionstopWatch(){
geoLoc.clearWatch(watchID);}</script></head><body><form><inputtype="button"onclick="getLocationUpdate();"value="Watch Update"/><inputtype="button"onclick="stopWatch();"value="Stop Watch"/></form></body></html>
**
【05】返回的位置对象的属性
返回的位置对象的属性
地理定位方法 getCurrentPosition() 和 getPositionUsingMethodName() 指定了检索位置信息的回调方法。
这些方法使用一个存储完整位置信息的 Position 对象异步调用。
这个 Position 对象指定了设备的当前地理位置。这个位置以一组带有方向和速度信息的地理坐标表示。
下面的表格描述了 Position 对象的属性。对于可选属性,如果系统没有提供值,则该属性值为 null。
属性 | 类型 | 描述 |
---|---|---|
coords | objects |
表示设备的地理位置。位置以一组带有方向和速度信息的地理坐标表示。 |
coords.latitude | Number |
十进制的纬度估值。值范围为 [-90.00, +90.00]。 |
coords.longitude | Number |
十进制的经度固执。值范围为 [-180.00, +180.00]。 |
coords.altitude | Number |
【可选】 WGS-84 球面以上的海拔高度固执,以米为单位计算。 如果没有相关数据则值为 |
coords.accuracy | Number |
【可选】 以米为单位的纬度和经度精确估值。 |
coords.altitudeAccuracy | Number |
【可选】 以米为单位的海拔高度精确估值。 数值越大越不精确。 |
coords.heading | Number |
【可选】 相对正北方向设备以顺时针方向运动计算的当前方向。 指南针的方向,0°表示正北,值为 |
coords.speed | Number |
【可选】 以米/每秒为单位的设备当前地面速度。 即每秒移动多少米,如果没有相关数据则值为 |
timestamp | date |
检索位置信息和创建 Position 对象的日期时间。 |
处理错误
地理定位是复杂的。非常需要我们捕获任意错误并处理它。
地理定位方法 getCurrentPosition() 和 watchPosition() 可以使用一个提供 PositionError 对象的错误处理回调方法。
这个对象有下列两属性。
属性 | 类型 | 描述 |
---|---|---|
code | Number |
错误码。 |
message | String |
错误描述信息。 |
下面这个表格描述了 PositionError 对象可能返回的错误码。
错误码 | 常量 | 描述 |
---|---|---|
0 | UNKNOWN_ERROR |
由于未知错误,检索设备位置信息失败。 |
1 | PERMISSION_DENIED |
由于应用程序没有权限使用位置服务,检索设备位置信息失败。 用户拒绝了定位服务的请求。 |
2 | POSITION_UNAVAILABLE |
设备位置信息无法确定。没有获取正确的地理位置信息。 位置无效。 |
3 | TIMEOUT |
不能在给定的最大超时区间内检索位置信息。 获取位置的操作超时。 |
在error对象中,除”code”属性表示出错数字外,还可以通过”message”属性获取出错的详细文字信息。该属性是一个字符串,包含与”code”属性值相对应的错误说明信息。
实例
function showError(error)
{
switch(error.code)
{
case error.PERMISSION_DENIED:
x.innerHTML="User denied the request for Geolocation."
break;
case error.POSITION_UNAVAILABLE:
x.innerHTML="Location information is unavailable."
break;
case error.TIMEOUT:
x.innerHTML="The request to get user location timed out."
break;
case error.UNKNOWN_ERROR:
x.innerHTML="An unknown error occurred."
break;
}
}
**
【06】
options选项
下面是 getCurrentPosition() 方法的实际语法:
getCurrentPosition(callback, ErrorCallback, options)
其中第三个参数是指定一组检索设备地理位置选项的 PositionOptions 对象。
下列选项可以指定为第三个参数:
属性 | 类型 | 描述 |
---|---|---|
enableHighAccuracy | Boolean |
布尔值,是否想要检索最精准的位置估值。默认值为 false。 属性是指定浏览器或移动设备尝试更精确地读取经度和纬度,默认值为false。当这个属性参数设置为true时,移动设备在定位计算上可能会花费更长时间,也容易导致消耗更多的移动设备电量。因此,如果无较高准确定位的需求,应该将参数设置为false或不设置。 |
timeout | Number |
timeout 属性就是 Web 应用程序要等待定位的毫秒数。 默认不限时。 |
maximumAge | Number |
用于缓存位置信息的过期时间毫秒数。 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。 |
如:
navigator.geolocation.getCurrentPosition(function(position){
drawMapCenteredAt(position.coords.latitude, positions.coords.longitude);
}, function(error){
console.log("Error code: " + error.code);
console.log("Error message: " + error.message);
}, {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 25000
});
这三个选项都是可选的,可以单独设置,也可以与其他选项一起设置。
除非确实需要非常精确的信息,否则建议保持enableHighAccuracy
的false
值(默认值)。将这个选项设置为true
需要更长的时候,而且在移动设备上还会导致消耗更多电量。类似地,如果不需要频繁更新用户的位置信息,那么可以将maximumAge
设置为Infinity
,从而始终都使用上一次的坐标信息。
例子:
navigator.geolocation.getCurrentPosition(function(pos){
console.log("当前地理位置的纬度: "+pos.coords.latitude);
console.log("当前地理位置的经度: "+pos.coords.longitude);
console.log("当前地理位置的精度: "+pos.coords.accuracy);
},function(err){
if (err.code == 1) {
// access is denied
}
}, {maximumAge: 75000});
【】魔芋测试:(在浏览器中无效。)
火狐截图:
**
**