GeolocationAPI学习,我写的挺枯燥的,直接跳到最后看示例。javascript
HTML5 Geolocation API的使用方法至关简单。请求一个位置信息,若是用户赞成,浏览器就会返回位置信息,该位置信息是经过支持HTML5地理定位功能的底层设备(手机、笔记本电脑等)提供给浏览器的。位置信息由维度、经度坐标和其余一些元数据组成。css
位置信息主要有一对维度和经度坐标组成。
例如坐标:维度:39.1722二、维度:-120.13778
其中维度(距离赤道以北或以南的数值表示)是39.17222,经度(距离英国格林威治以东或以西的数值表示)是-120.13778。html
经纬度能够用如下两种方式表示:java
十进制格式(例如:39.17222); DMS(Degree Minute Second,角度)格式(例如,66°33' 38" )
除了经纬度,HTML5 Geolocation还提供了位置坐标的准确度,以及根据浏览器的硬件设备是否可以提供海拔、海拔准确度、形式方向和速度等元数据,若没法提供则返回null。git
Geolocation仅是检索设备提供位置信息的API,而且经过该API检索到的数据只具备某种程度的准确性。并不能保证设备返回的实际位置是精确的。编程
设备可使用的数据源:浏览器
IP地址 三维坐标 GPS(Global Positioning System,全球定位系统) 从RFID,Wi-Fi和蓝牙到Wi-Fi的MAC地址: GSM或CDMA手机的ID 用户自定义数据
基于IP地址的地理定位的实现方式是:自动查询用户的IP地址,而后检索器注册的物理地址。所以,若是用户的IP地址是ISP提供的,其位置每每是由服务供应商的物理地址决定的,该地址可能距离用户数公里。服务器
表5-1 基于IP地址的地理位置数据的优缺点 优势 缺点 任何地方均可用 不精确 在服务器端处理 运算代价大
只要能够看到天空的地方,GPS就能够提供很是精确的定位。GPS定位是经过手机运行在地球周围的多个GPS卫星的信号实现的。可是,他的定位时间可能较长,所以它不适合须要快速响应的应用程序。dom
表5-2 基于GPS的地理定位数据的优缺点 优势 缺点 很精确 定位时间长,用户耗电量大 室内效果很差 须要额外硬件设备
基于WiFi的地理定位信息是经过三角距离计算得出的,这个三角距离值得是用户当前位置到一只的多个WiFi接入点的距离。不一样于GPS,WiFi在室内也很是准确。函数
表5-3 基于Wi-Fi的地理定位的优缺点 优势 缺点 精确 在乡村这些无线接入点较少的地区效果很差 可在室内使用 能够简单、快捷定位
基于手机的地理定位信息是经过用户到一些基站的三角距离肯定的。这种方法可提供至关准确的位置结果。这种方法一般同基于Wi-Fi和基于GPS的地理定位信息结合使用。表5-4是基于手机的地理定位数据的优缺点。
表5-4 基于手机的地理定位数据的优缺点 优势 缺点 至关准确 须要可以访问手机或其modem的设备 可在室内使用 在基站较少的偏远地区效果很差 能够简单、快捷定位
应用程序可能容许用户输入他们的地理、邮政编码和其余的一些详细信息。应用程序能够利用这些信息来提供位置感知服务。
表5-5 用户自定义的地理定位数据的优缺点 优势 缺点 用户能够得到比程序定位服务更准确的位置数据 可能很不许确,特别是当用户位置变动后 容许地理定位服务结果做为备用位置信息 用户自行输入可能比自动检测更快
目前主流浏览器都支持。
function loadDemo(){ if(navigator.geolocation){ document.getElementById('support').innerHTML = "Geolocation supported"; }else{ document.getElementById("support").innerHTML = "Geolocation is not supported in your browser."; } }
有两种类型的位置要求:
1 单次定位的请求
2 重复性的位置更新请求
1 只检索或请求一次用户位置便可。例如,若是要查询在接下来的一个小时内放映某大片的最近的电影院。就可使用代码清单5-2所示的简单HTML5 Geolocation API.
单次定位请求
void getCurrentPosition(in PositionCallback successCallback, in optional PositionErrorCallback errorCallback, in optional PositionOptions options);
这个函数接受一个必须参数和两个可选参数
函数参数successCallback为浏览器指明位置数据可用时调用的函数。由于像获取位置数据这样的操做可能须要较长的时间才能完成,因此这个参数很重要。没有用户但愿在检索位置时浏览器被锁定,也没有开发人员但愿它的程序无限期被暂停(特别是要成功取得位置信息,常常必须等待用户的许可)。successCallback是收到实际位置信息并进行处理的地方。
跟绝大多数编程场景同样,最好提早准备出错处理。位置信息请求极可能由于一些不可控因素失败,对于这些状况,你可能须要提供一个跟用户解释或者提示其重试的errorCallback函数。虽然此参数是可选的,不过建议选用。
最后,options对象能够调整HTML5 Geolocation服务的数据收集方式。这是一个可选参数,随后在论。
假设在页面上已经建立了一个名为updateLocation()的Javascript函数,它使用最新的位置数据更新页面内容,一样的,也建立了一个handleLocationError()函数来处理错误状况。而请求访问用户位置的核心代码以下所示:
navigator.geoocation.getCurrentPosition(updateLocation,handleLocationError);
updateLocation()函数:
只要浏览器具有访问位置信息的条件,就会调用updateLocation()函数,该函数只接受一个参数:位置对象.这个对象包含坐标(coords特性)和一个获取位置数据时的时间戳。在实际开发中不必定须要时间戳,重要位置数据都包含在了coords特性中。
如下是前三个特性:
latitude(纬度)
logitude(经度)
accuracy(准确度)
latitude和longitude将包含HTML5Geolocaiton服务测定的最佳十进制用户位置。accuracy将以m指定维度和经度值与实际位置的差距,置信度为95%。
function updateLocation(position){ var latitude = position.coords.latitude; var longitude = position.coords.longitude; var accuracy = position.coords.accuracy; var timestamp = position.timestamp; document.getElementById("latitude").innerHTML = latitude; document.getElementById('longitude').innerHTML = longitude; document.getElementById('accuracy').innerHTML = accuracy; document.getElementById('timestamp').innerHTML = timestamp; }
由于位置计算服务极可能出错,对于HTML5 Geolocation应用程序来讲处理错误很是重要。而该API定义了全部须要处理的错误状况的编号。错误编号设置在错误对象中,错误对象做为code参数传递给错误处理程序。这些错误编号为:
PERMISSION_DENIED(错误编号为1)---用户选择拒绝浏览器得到其位置信息。
POSITION_UNAVAILABLE(错误编号为2)---尝试获取用户位置数据,但失败了。
TIMEOUT(错误编号为3)--设置了可选的timeout值。尝试肯定用户位置的过程超时。
function hadleLocationError(error){ switch(error.code){ case 0: updateStatus("There was an error while retrieving your location" + error.message); break; case 1: updateStatus("The user prevented this page from retrieving a location"); break; case 2: updateStatus("The browser was unable to determine your location" + error.message); break; case 3: updateStatus("The browser timed out before retrieving the location"); break; } }
若是要同时处理正常状况和错误状况,就应该把注意力集中到三个可选参数(enableHight-Accuracy,timeout和maximumAge)上,将这三个可选参数传递给HTML5 Geolocation服务以调整数据收集方式。请注意,这三个参数可使用JSON对象传递,这样更便于添加到HTML5Geolocation请求调用中。
enableHighAccuracy:启用该参数,则通知浏览器启用HTML5 Geolocation服务的高精度模式。参数的默认值为false。若是启用该参数,可能没有任何差异,也可能会致使机器花费更多的时间和资源来肯定位置,因此请谨慎。 timeout:可选值,单位为ms,告诉浏览器计算当前位置所容许的最长时间。若是在这个时间内未完成计算,就会调用错误处理程序。其默认值为Infinity,即无穷大或无限制。 maximumAge : 这个值表示浏览器从新计算位置的时间间隔。它是一个以ms为单位的值。此值默认为0,这意味着浏览器每次请求超时时必须当即从新计算位置。
注意:地理定位API不容许咱们为浏览器指定多长时间从新计算一次位置信息。这是彻底由浏览器的实现所决定的。咱们能作的就是告诉浏览器maximumAge的返回值是什么。实际频率是咱们一个没法控制的细节。
如今更新咱们的位置请求,让其包含一个使用JSON对象表示的可选参数,以下所示:
navigator.geolocation.getCurrentPostion(updateLocation,handleLocationError ,{timeout:10000});
这个新调用告诉HTML5 Geolocation,任何处理时间超过10s的位置请求都应该调用handleLocationError函数处理编号对应的TIMEOUT的错误。
有时候,仅更新一次是不够的。还好,Geolocation服务的设计者使应用程序能够在单词请求用户定位和以既定时间间隔屡次请求用户位置间相互转换。事实上,转换的方式很简单,只须要变换函数请求便可,以下所示:
一次更新:
navigator.geolocation.getCurrentPosition(updateLocation,handleLocationError);
重复更新:
navigator.geolocation.wathcPosition(updateLocation,handleLocationError); // 只要用户的位置发生变化,Geolocation服务就会调用updateLocaiton处理程序,它的效果就像是程序在监视用户的位置,并会在其变化时及时通知用户同样。
重复更新的好处:若有一个页面,随着观察者在城镇周围移动,网页上的方向指示也随之改变,再假设关于一个加油站的页面,随着用户开车在高速公路上持续行驶,页面不断更新显示最近的加油站。另外,还能够在一个页面中记录和传送用户位置来实现回溯已走的路线。若是位置信息一发生改变,就能传递给应用程序,那么前面所假设的全部服务都会变得很容易实现。
若是应用程序再也不须要接受有关用户的持续位置更新,则只需调用clearWatch()函数,以下所示:
navigator.geolocation.clearWatch(watchId);
watchId表示一个惟一的监视请求以便未来取消监视。因此,若是应用程序要中止接收位置更新信息,能够参照如下代码。
var watchId = navigator.geolocation.watchPosition(updateLocation,handleLocationError); // 基于持续更新的位置信息的一些功能 //...... // ok,如今咱们能够中止接收位置更新信息了 navigator.geolocation.clearWatch(watchId);
接下来咱们使用屡次请求特性构建一个简单有用的Web应用程序---距离跟踪器。
基于HTML5 Geolocation提供的强大定位服务,开发人员能够建立一个网页来跟踪从网页被加载的地方到目前所在位置所通过的距离。虽然它在台式机上不大实用,可是对于手机是很理想的,只要在手机浏览器中打开这个示例页面并授予其位置访问的权限,每隔几秒钟,应用程序就会根据刚才走过的距离更新,并将其增长到总距离中。
距离计算公式使用Haversine公式来实现,这个公式可以根据经纬度来计算地球两点距离。代码以下(这个公式后面看看有没有时间研究一下,有就后续补上):
Number.prototype.toRadians = function() { return this * Math.PI / 180; } function distance(latitude1, longitude1, latitude2, longitude2) { // R is the radius of the earth in kilometers var R = 6371; var deltaLatitude = (latitude2-latitude1).toRadians(); var deltaLongitude = (longitude2-longitude1).toRadians(); latitude1 = latitude1.toRadians(), latitude2 = latitude2.toRadians(); var a = Math.sin(deltaLatitude/2) * Math.sin(deltaLatitude/2) + Math.cos(latitude1) * Math.cos(latitude2) * Math.sin(deltaLongitude/2) * Math.sin(deltaLongitude/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; return d; }
以简单的表格进行展现,分行显示纬度、经度、准确度和以ms为单位的时间戳。
<h1>HTML5 Geolocation Distance Tracker</h1> <p id="status">HTML5 Geolocation is <strong>not</strong> supported in your browser.</p> <h2>Current Position:</h2> <table border="1"> <tr> <th width="40" scope="col"><h5>Latitude</h5></th> <td width="114" id="latitude">?</td> </tr> <tr> <td> Longitude</td> <td id="longitude">?</td> </tr> <tr> <td>Accuracy</td> <td id="accuracy">?</td> </tr> <tr> <td>Last Timestamp</td> <td id="timestamp">?</td> </tr> </table> <h4 id="currDist">Current distance traveled: 0.0 km</h4> <h4 id="totalDist">Total distance traveled: 0.0 km</h4>
在Geolocation数据处理部分,第一段Javascript代码应该看起来很熟悉了。以前咱们设置过一个处理程序loadDemo(),它会在页面加载完成时候执行。这个脚本会检测浏览器是否支持HTML5 Geolocation,而后将检测结果显示在页面上。最后,代码会请求检测用户位置。
var totalDistance = 0.0; var lastLat; var lastLong; function updateStatus(message){ document.getElementById("status").innerHTML = message; } function loadDemo(){ if(navigator.geolocation){ updateStatus.geolocation(){ updateStatus("HTML5 Geolocation is supported in your browser"); navigator.geolocation.watchPosition(updateLocation,handleLocationError,{maximumAge:20000}); } } } window.addEventListener('load',loadDemo,true);
对于错误处理,咱们使用以前提到过的那段代码,咱们将检查收到的全部错误编号,并更新页面上的状态信息。
function handleLocationError(error) { switch(error.code) { case 0: updateStatus("There was an error while retrieving your location: " + error.message); break; case 1: updateStatus("The user prevented this page from retrieving a location."); break; case 2: updateStatus("The browser was unable to determine your location: " + error.message); break; case 3: updateStatus("The browser timed out before retrieving the location."); break; } }
而咱们大部分工做都将在updateLocation()函数中实现,此函数中咱们将使用最新数据来更新页面并计算路程。代码以下:
function updateLocation(position) { var latitude = position.coords.latitude; var longitude = position.coords.longitude; var accuracy = position.coords.accuracy; var timestamp = position.timestamp; document.getElementById("latitude").innerHTML = latitude; document.getElementById("longitude").innerHTML = longitude; document.getElementById("accuracy").innerHTML = accuracy; document.getElementById("timestamp").innerHTML = timestamp; // sanity test... don't calculate distance if accuracy // value too large if (accuracy >= 500) { updateStatus("Need more accurate values to calculate distance."); return; } // calculate distance 计算距离 if ((lastLat != null) && (lastLong != null)) { var currentDistance = distance(latitude, longitude, lastLat, lastLong); document.getElementById("currDist").innerHTML = "Current distance traveled: " + currentDistance.toFixed(4) + " km"; totalDistance += currentDistance; document.getElementById("totalDist").innerHTML = "Total distance traveled: " + currentDistance.toFixed(4) + " km"; } lastLat = latitude; lastLong = longitude; updateStatus("Location successfully updated."); }
首先获取坐标数据后,记录全部信息。即收集经纬度,准确度和时间戳,而后将这些数据更新到表格中。
时间戳对于用户而言没有意义,主要是提供程序使用,能够将时间戳替换成便于用户识别的时间指示器,或者将其彻底删除。
准确度是以米为单位的,显示不许确的值会向用户提供错误的位置信息,所以,须要将过滤掉有全部低经度的位置更新数据。
if (accuracy >= 500) { updateStatus("Need more accurate values to calculate distance."); return; }
完整代码以下
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>HTML5 Geolocation Odometer</title> <link rel="stylesheet" href="styles.css"> </head> <body onload="loadDemo()"> <h1>HTML5 Geolocation Distance Tracker</h1> <p id="status">HTML5 Geolocation is <strong>not</strong> supported in your browser.</p> <h2>Current Position:</h2> <table border="1"> <tr> <th width="40" scope="col"><h5>Latitude</h5></th> <td width="114" id="latitude">?</td> </tr> <tr> <td> Longitude</td> <td id="longitude">?</td> </tr> <tr> <td>Accuracy</td> <td id="accuracy">?</td> </tr> <tr> <td>Last Timestamp</td> <td id="timestamp">?</td> </tr> </table> <h4 id="currDist">Current distance traveled: 0.0 km</h4> <h4 id="totalDist">Total distance traveled: 0.0 km</h4> <script type="text/javascript"> var totalDistance = 0.0; var lastLat; var lastLong; Number.prototype.toRadians = function() { return this * Math.PI / 180; } function distance(latitude1, longitude1, latitude2, longitude2) { // R is the radius of the earth in kilometers var R = 6371; var deltaLatitude = (latitude2-latitude1).toRadians(); var deltaLongitude = (longitude2-longitude1).toRadians(); latitude1 = latitude1.toRadians(), latitude2 = latitude2.toRadians(); var a = Math.sin(deltaLatitude/2) * Math.sin(deltaLatitude/2) + Math.cos(latitude1) * Math.cos(latitude2) * Math.sin(deltaLongitude/2) * Math.sin(deltaLongitude/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; return d; } function updateStatus(message) { document.getElementById("status").innerHTML = message; } function loadDemo() { if(navigator.geolocation) { updateStatus("HTML5 Geolocation is supported in your browser."); navigator.geolocation.watchPosition(updateLocation, handleLocationError, {maximumAge:20000}); } } function updateLocation(position) { var latitude = position.coords.latitude; var longitude = position.coords.longitude; var accuracy = position.coords.accuracy; var timestamp = position.timestamp; document.getElementById("latitude").innerHTML = latitude; document.getElementById("longitude").innerHTML = longitude; document.getElementById("accuracy").innerHTML = accuracy; document.getElementById("timestamp").innerHTML = timestamp; // sanity test... don't calculate distance if accuracy // value too large if (accuracy >= 500) { updateStatus("Need more accurate values to calculate distance."); return; } // calculate distance if ((lastLat != null) && (lastLong != null)) { var currentDistance = distance(latitude, longitude, lastLat, lastLong); document.getElementById("currDist").innerHTML = "Current distance traveled: " + currentDistance.toFixed(4) + " km"; totalDistance += currentDistance; document.getElementById("totalDist").innerHTML = "Total distance traveled: " + currentDistance.toFixed(4) + " km"; } lastLat = latitude; lastLong = longitude; updateStatus("Location successfully updated."); } function handleLocationError(error) { switch(error.code) { case 0: updateStatus("There was an error while retrieving your location: " + error.message); break; case 1: updateStatus("The user prevented this page from retrieving a location."); break; case 2: updateStatus("The browser was unable to determine your location: " + error.message); break; case 3: updateStatus("The browser timed out before retrieving the location."); break; } } </script> </body> </html>
Geolocation匆匆忙忙结束了,请你们当个键盘侠,多多指点,毕竟键多识广。