摘要:如果應用程序不再需要接受有關用戶的持續位置更新,則只需調用函數,如下所示表示一個唯一的監視請求以便將來取消監視。
GeolocationAPI學習,我寫的挺枯燥的,直接跳到最后看示例。
5.1 位置信息HTML5 Geolocation API的使用方法相當簡單。請求一個位置信息,如果用戶同意,瀏覽器就會返回位置信息,該位置信息是通過支持HTML5地理定位功能的底層設備(手機、筆記本電腦等)提供給瀏覽器的。位置信息由維度、經度坐標和其他一些元數據組成。
5.1.1 經度和維度坐標位置信息主要有一對維度和經度坐標組成。
例如坐標:維度:39.17222、維度:-120.13778
其中維度(距離赤道以北或以南的數值表示)是39.17222,經度(距離英國格林威治以東或以西的數值表示)是-120.13778。
經緯度可以用以下兩種方式表示:
十進制格式(例如:39.17222); DMS(Degree Minute Second,角度)格式(例如,66°33" 38" )
除了經緯度,HTML5 Geolocation還提供了位置坐標的準確度,以及根據瀏覽器的硬件設備是否能夠提供海拔、海拔準確度、形式方向和速度等元數據,若無法提供則返回null。
5.1.2 位置的由來Geolocation僅是檢索設備提供位置信息的API,并且通過該API檢索到的數據只具有某種程度的準確性。并不能保證設備返回的實際位置是精確的。
設備可以使用的數據源:
IP地址 三維坐標 GPS(Global Positioning System,全球定位系統) 從RFID,Wi-Fi和藍牙到Wi-Fi的MAC地址: GSM或CDMA手機的ID 用戶自定義數據5.1.3 IP地址地理定位數據
基于IP地址的地理定位的實現方式是:自動查詢用戶的IP地址,然后檢索器注冊的物理地址。因此,如果用戶的IP地址是ISP提供的,其位置往往是由服務供應商的物理地址決定的,該地址可能距離用戶數千米。
表5-1 基于IP地址的地理位置數據的優缺點 優點 缺點 任何地方都可用 不精確 在服務器端處理 運算代價大5.1.4 GPS地理定位數據
只要可以看到天空的地方,GPS就可以提供非常精確的定位。GPS定位是通過手機運行在地球周圍的多個GPS衛星的信號實現的。但是,他的定位時間可能較長,因此它不適合需要快速響應的應用程序。
表5-2 基于GPS的地理定位數據的優缺點 優點 缺點 很精確 定位時間長,用戶耗電量大 室內效果不好 需要額外硬件設備5.1.5 Wi-Fi地理定位數據
基于WiFi的地理定位信息是通過三角距離計算得出的,這個三角距離值得是用戶當前位置到一只的多個WiFi接入點的距離。不同于GPS,WiFi在室內也非常準確。
表5-3 基于Wi-Fi的地理定位的優缺點 優點 缺點 精確 在鄉村這些無線接入點較少的地區效果不好 可在室內使用 可以簡單、快捷定位5.1.6 手機地理定位數據
基于手機的地理定位信息是通過用戶到一些基站的三角距離確定的。這種方法可提供相當準確的位置結果。這種方法通常同基于Wi-Fi和基于GPS的地理定位信息結合使用。表5-4是基于手機的地理定位數據的優缺點。
表5-4 基于手機的地理定位數據的優缺點 優點 缺點 相當準確 需要能夠訪問手機或其modem的設備 可在室內使用 在基站較少的偏遠地區效果不好 可以簡單、快捷定位5.1.7 用戶自定義的地理定位數據
應用程序可能允許用戶輸入他們的地理、郵政編碼和其他的一些詳細信息。應用程序可以利用這些信息來提供位置感知服務。
表5-5 用戶自定義的地理定位數據的優缺點 優點 缺點 用戶可以獲得比程序定位服務更準確的位置數據 可能很不準確,特別是當用戶位置變更后 允許地理定位服務結果作為備用位置信息 用戶自行輸入可能比自動檢測更快5.2 Geolocation的瀏覽器支持情況
目前主流瀏覽器都支持。
5.4 使用HTML5 Geolocation API 5.4.1 瀏覽器支持檢查function loadDemo(){ if(navigator.geolocation){ document.getElementById("support").innerHTML = "Geolocation supported"; }else{ document.getElementById("support").innerHTML = "Geolocation is not supported in your browser."; } }5.4.2 位置請求
有兩種類型的位置要求:
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; }handleLocationError()函數
因為位置計算服務很可能出錯,對于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的錯誤。
2 重復性的位置更新請求有時候,僅更新一次是不夠的。還好,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);4.5 使用HTML5 Geolocation構建實時應用
接下來我們使用多次請求特性構建一個簡單有用的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; }4.5.1 編寫HTML顯示代碼
以簡單的表格進行展示,分行顯示緯度、經度、準確度和以ms為單位的時間戳。
HTML5 Geolocation Distance Tracker
HTML5 Geolocation is not supported in your browser.
Current Position:
Latitude |
? |
---|---|
Longitude | ? |
Accuracy | ? |
Last Timestamp | ? |
在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; }
完整代碼如下
HTML5 Geolocation Odometer HTML5 Geolocation Distance Tracker
HTML5 Geolocation is not supported in your browser.
Current Position:
Latitude |
? |
---|---|
Longitude | ? |
Accuracy | ? |
Last Timestamp | ? |