前端开发中的地理定位问题小总结
項目中遇到地理定位的問題,沒遇過不知道,遇過就發(fā)現(xiàn)這是個比較坑的問題。這個問題其實困擾了我挺久的,還不如一次性了解清楚。所以本文進(jìn)行了一些小總結(jié),先簡單總結(jié)我看過的關(guān)于定位技術(shù)的資料,然后介紹前端開發(fā)中的可選定位方案,以及存在的一些問題。
定位技術(shù)
概念上很好理解,就是定位你在哪里的技術(shù)。常見的定位方式有基站定位,WiFi定位,IP定位,GPS定位等。
基站定位
基站是能進(jìn)行信號交換的站點。手機(jī)能接受信號,打電話就是通過手機(jī)基站。這些基站是由國家移動通信運(yùn)營商建的,比如中國移動,中國聯(lián)通,中國電信。原理如下,通過手機(jī)接受不同幾個基站的信號強(qiáng)度來判斷二者之間距離,當(dāng)然基站的位置信息本來是已知的,所以手機(jī)的位置就知道了。前提是手機(jī)必須處于SIM卡注冊狀態(tài)下。由于手機(jī)信號會受干擾,基站定位精度較低。而且精度也受基站的密度影響,密度越大越精準(zhǔn)。
WiFi定位
WiFi是無線上網(wǎng)的一種技術(shù)。平時手機(jī)不連上WiFi的功能就能定位。大致的原理是,WiFi信號被設(shè)備檢測到,數(shù)據(jù)庫記錄這個WiFi信號和設(shè)備對應(yīng)的位置。當(dāng)它被越來越多的設(shè)備檢測到,它的位置就可以利用這些數(shù)據(jù)通過某種算法來得出。由于信號隨著距離的增加而減少,根據(jù)設(shè)備獲取到的WiFi信號強(qiáng)度就可以計算出兩者之間的距離。知道了周圍幾個點,以及與這些點之間的距離,待定位的設(shè)備位置就不難計算出來了。WiFi定位是由谷歌提出的,主要解決了室內(nèi)定位的問題。缺點是,當(dāng)某個WiFi搬家的時候,數(shù)據(jù)庫沒有及時更新,就會出現(xiàn)定位不準(zhǔn)的問題。
IP定位
每個能聯(lián)網(wǎng)的設(shè)備都被分配了一個ip,通過查到數(shù)據(jù)庫,可以粗略地知道這個ip所在的地理位置。你可以點這里試試IP定位。
GPS定位
GPS,全稱Global Position System,全球定位系統(tǒng),簡單的說,就是天上有很多衛(wèi)星(24顆),通過4顆衛(wèi)星的位置以及衛(wèi)星與待定位設(shè)備之間的距離,計算出該設(shè)備的位置。GPS精度高,但費(fèi)電。還有在室內(nèi)的時候,訊號就會被阻擋 ,所以室內(nèi)GPS定位不準(zhǔn)。
AGPS定位
AGPS是Assisted GPS的意思。由于GPS定位最初使用都有一個冷啟動時間(2-3分鐘),在此之前先借助其他的定位方式進(jìn)行粗略地定位,然后可以較快地根據(jù)GPS進(jìn)行精確定位。一般借用的輔助定位方式為基站定位。
定位技術(shù)比較
以上的定位方式各有優(yōu)缺點,實際開發(fā)中一般同時采用多個定位方式進(jìn)行定位。
| 基站定位 | 能通電話的手機(jī) | 快速,耗能小 | 受基站的密度影響,信號也會被干擾 |
| WiFi定位 | 有WiFi的地方 | 精度尚可,解決室內(nèi)定位問題 | WiFi數(shù)據(jù)庫更新不及時 |
| IP定位 | 能上網(wǎng)的設(shè)備 | 精度依賴數(shù)據(jù)庫 | |
| GPS定位 | 室外 | 精確度高 | 不能用于室內(nèi),首次定位較慢 |
| AGPS定位 | 同上 | 同上,解決了首次定位慢的問題 | 不能用于室內(nèi) |
開發(fā)實戰(zhàn)
一般情況下,我們肯定不會自己去實現(xiàn)這些定位技術(shù)的算法,而是借助于第三方的SDK。
h5開發(fā)中的方案大體來說有以下幾種:
- 微信JSSDK定位
- HTML5定位
- 高德JS API定位
這些定位基本上都是需要獲取用戶的授權(quán)。
微信JSSDK定位
利用微信的JSSDK來定位,簡單代碼如下。具體可以參考開發(fā)手冊。
wx.config({debug: false,appId: json.appid,timestamp: json.timestamp,nonceStr: json.nonceStr,signature: json.signature,jsApiList: ['getLocation']});wx.error(function (res) {console.log(res.errMsg); options.callback();});wx.ready(function () { wx.getLocation({type: 'wgs84', // 默認(rèn)為wgs84的gps坐標(biāo),如果要返回直接給openLocation用的火星坐標(biāo),可傳入'gcj02'success: function (res) {var latitude = res.latitude; // 緯度,浮點數(shù),范圍為90 ~ -90var longitude = res.longitude; // 經(jīng)度,浮點數(shù),范圍為180 ~ -180。 console.log('微信定位成功;'); },fail: function(){console.log('微信定位失敗;'); }});});在網(wǎng)上沒有找到微信定位的原理,估計就是混合定位的方式。微信定位比較好用,只要你授權(quán)了定位,成功率比較高。缺點是,只能有微信客戶端才能調(diào)用微信JSSDK。
但我發(fā)現(xiàn)在微信web開發(fā)者工具中,定位不準(zhǔn)確。原因不詳。
HTML5定位
HTML5定位是HTML5新增的特性。官網(wǎng)上對它使用的定位技術(shù)進(jìn)行了描述:
The Geolocation API defines a high-level interface to location information associated only with the device hosting the implementation, such as latitude and longitude. The API itself is agnostic of the underlying location information sources. Common sources of location information include Global Positioning System (GPS) and location inferred from network signals such as IP address, RFID, WiFi and Bluetooth MAC addresses, and GSM/CDMA cell IDs, as well as user input. No guarantee is given that the API returns the device’s actual location.
簡而言之,HTML5定位是優(yōu)先采用GPS,失敗就用網(wǎng)絡(luò)信號,比如IP地址,WiFi,藍(lán)牙等等。而且它明確說明,不能保證返回結(jié)果的正確性。
簡單例子如下,具體的API可參考這篇博客。
if (navigator.geolocation) {console.log("h5 定位中");navigator.geolocation.getCurrentPosition(function(position) {var latitude = position.coords.latitude;var longitude = position.coords.longitude;console.log('h5定位成功;'); }, function(error) {console.log('h5定失敗;'); }) }Geolocation API規(guī)范提供了一套保護(hù)用戶隱私的機(jī)制,必須先得到用戶明確許可,才能獲取用戶的位置信息。
看起來這是個很不錯的方式,現(xiàn)代瀏覽器都已經(jīng)支持HTML5了。不幸的是,Chrome瀏覽器從50版本開始,http協(xié)議的網(wǎng)址是不能用了。控制臺會有這樣的提示:
getCurrentPosition() and watchPosition() no longer work on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.高德JS API定位
以下是高德官網(wǎng)的說明。你可以點擊這里來測試高德的定位功能。
AMap.Geolocation定位服務(wù)插件。融合了瀏覽器定位、高精度IP定位、安卓定位sdk輔助定位等多種手段,提供了獲取當(dāng)前準(zhǔn)確位置、獲取當(dāng)前城市信息、持續(xù)定位(瀏覽器定位)等功能。
由于Chrome、IOS10等已不再支持非安全域的瀏覽器定位請求,為保證定位成功率和精度,請盡快升級您的站點到HTTPS。
高德用Geolocation.getCurrentPosition獲取精確位置的流程如下:
在PC端,因為原生接口成功率很低,JS-API會優(yōu)先調(diào)用精確IP定位服務(wù),在IP定位失敗的時候,嘗試使用瀏覽器原生定位接口進(jìn)行定位,如果原生定位接口也定位失敗,則返回error事件或回調(diào)error信息。定位成功之后我們會對瀏覽器定位的經(jīng)緯度結(jié)果進(jìn)行向高德坐標(biāo)的轉(zhuǎn)化,并對所有有效定位結(jié)果融合地址信息后返回complete事件或者回調(diào)complete信息。
在移動端,如果開發(fā)者開啟了sdk輔助定位,那么安卓手機(jī)上我們會優(yōu)先嘗試調(diào)用sdk的定位接口,失敗之后優(yōu)先調(diào)用瀏覽器原生定位接口進(jìn)行定位,瀏覽器定位失敗之后嘗試進(jìn)行精確IP定位,如果以上三種定位全部嘗試失敗則返回error事件或回調(diào)error信息,否則和PC端的一樣,定位成功之后進(jìn)行高德坐標(biāo)轉(zhuǎn)化和地址融合。
我們在定位的回調(diào)或者事件響應(yīng)中返回了message字段,message字段明確指出了每一步的成功和失敗原因。
以及高德對 getCurrentPosition定位失敗的原因說明:
IP精確定位失敗,message包含‘Get ipLocation failed.’信息,精確IP定位服務(wù)無法完全覆蓋所有IP和用戶,故而失敗;
sdk定位失敗,請檢查sdk的key是否設(shè)置好,以及webview的定位權(quán)限及應(yīng)用和系統(tǒng)的定位權(quán)限是否開啟。
瀏覽器定位失敗,有多種情況:
具體的代碼例子如下:
AMap.service('AMap.Geolocation', function() {geolocation = new AMap.Geolocation({enableHighAccuracy: true, //是否使用高精度定位,默認(rèn):truetimeout: 10000, //超過10秒后停止定位,默認(rèn):無窮大zoomToAccuracy: true, //定位成功后調(diào)整地圖視野范圍使定位位置及精度范圍視野內(nèi)可見,默認(rèn):falsebuttonPosition: 'LB', //顯示定位按鈕的位置 ,右下角 }); geolocation.getCurrentPosition();AMap.event.addListener(geolocation, 'complete', onComplete); //返回定位信息AMap.event.addListener(geolocation, 'error', onError); //返回定位出錯信息 })我做了一點小測試,結(jié)果如下:
A處:我的實際地址 B處: 我的IP地址+ PC端+ Chrome:B處+ IE:B處+ Safari:B處 + 手機(jī)端(安卓)+ 數(shù)據(jù)+ 自帶瀏覽器:A處偏一點+ 微信瀏覽器:A處+ Chrome:合肥市+ Safari:準(zhǔn)確+ WiFi+ 自帶瀏覽器:A處+ 微信瀏覽器:A處+ Chrome:杭州市+ Safari:準(zhǔn)確結(jié)果分析:PC端定位都是IP,所以是精確IP定位;在手機(jī)端,由于自帶瀏覽器和微信瀏覽器都支持HTML5定位(即瀏覽器定位,訪問前也有授權(quán)操作),所以都返回了同樣的結(jié)果;對于Chrome,瀏覽器定位不管用了,WiFi的IP定位定準(zhǔn)確了城市,而3G下的IP定位定到了手機(jī)號碼歸屬地。
那么,問題是對于這些定位不成功的例子怎么來解決?
我的方案
最初,我只用高德地圖的定位來做。但是時好時壞,我瞎折騰,又添加瀏覽器定位。然后想想這個在附在微信公眾號上的,于是又添加了微信JSSDK的方式。
所以,這個項目使用的定位方案是這樣的:同時調(diào)用微信定位,瀏覽器定位,高德定位,以最快出結(jié)果的為準(zhǔn)。想想三重保障是不是很完美了?
現(xiàn)實很殘酷,問題還很多,不然就不會有這篇文章了。
本來我還緩存了一定時間的城市和位置信息,但考慮到出錯的情況,還是取消緩存比較恰當(dāng)。
分析下來,其實瀏覽器定位的方式已經(jīng)包括在高德定位了。由于微信定位的高成功率,方案可以調(diào)整為:判斷是否為微信客戶端,是的話優(yōu)先調(diào)用微信定位,若微信定位失敗再調(diào)用高德;否的話,直接調(diào)用高德定位。
存在的問題
由于有些測試需要在項目上線后才好測試,我只是做一些分析猜測。據(jù)我所了解,目前的問題主要考慮的是高德定位失敗后怎么辦?
而高德失敗的主要原因也就是瀏覽器定位失敗,條件允許的話把網(wǎng)站(只需要那個頁面)升級到HTTPS就好了。
那網(wǎng)址即使已經(jīng)HTTPS協(xié)議的了呢?我們換個角度來思考一下。
從產(chǎn)品的角度出發(fā),無論怎么樣還是要考慮一定不成功的情況,那就提供手動輸入地址的功能吧。這就萬無一失了。
參考資料:
- http://www.cnblogs.com/magicboy110/archive/2010/12/09/1901669.html GPS定位原理
- https://www.zhihu.com/question/20355764/answer/26765991 WiFi定位原理
- http://www.pmcaff.com/article/index/492872948080768?from=related&pmc_param%5Bentry_id%5D=414603611639936 我們常用的手機(jī)定位方法
- http://www.cnblogs.com/syfwhu/p/5084115.html 常見手機(jī)定位方式淺談
- http://www.jianshu.com/p/a776ed702765 常用手機(jī)定位原理
- http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE 微信JSSDK說明文檔
- https://www.w3.org/TR/geolocation-API/ HTML5 geolocation api
- http://www.cnblogs.com/tugenhua0707/p/4520832.html html5獲取地理位置信息API
- https://developers.google.com/web/updates/2016/04/geolocation-on-secure-contexts-only
Geolocation API Removed from Unsecured Origins in Chrome 50 - http://lbs.amap.com/api/javascript-api/reference/location 高德地圖定位api
- http://lbs.amap.com/faq/web/javascript-api/80 高德定位失敗原因說明
轉(zhuǎn)載請注明出處:http://blog.csdn.net/fen747042796 野草園
歡迎關(guān)注我的知乎:野蠻的小小芬
總結(jié)
以上是生活随笔為你收集整理的前端开发中的地理定位问题小总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL学习笔记-从基础到进阶
- 下一篇: RDS2016 Multipoint R