地理定位原理簡(jiǎn)解及推薦Cordova插件使用

看到群友在折騰地理定位,簡(jiǎn)單寫一下,不過(guò)是基于一段時(shí)間前的經(jīng)驗(yàn),權(quán)做參考吧。

首先我們了解一下地理定位的基本知識(shí):

手機(jī)定位方式

定位即獲取用戶當(dāng)前經(jīng)緯度,手機(jī)定位方式常見有三種:

  1. GPS/北斗:根據(jù)系統(tǒng)GPS/北斗模塊通過(guò)與衛(wèi)星通信實(shí)時(shí)計(jì)算獲取經(jīng)緯度,精度10-100米左右,限制是容易受環(huán)境影響,在室內(nèi)幾乎不起作用。
  2. 基站:根據(jù)運(yùn)營(yíng)商基站位置計(jì)算經(jīng)緯度,基站可能離手機(jī)百米甚至上千米遠(yuǎn),所以誤差較大,精度100-3000米不等,限制是定位較慢,精度差。
  3. WIFI:根據(jù)周圍WIFI路由器位置計(jì)算經(jīng)緯度,在城市范圍,網(wǎng)絡(luò)節(jié)點(diǎn)比較密集,所以城市精度高點(diǎn),精度100-200米左右,限制是受周圍WIFI數(shù)量和分布影響,需要打開手機(jī)WIFI開關(guān)。

混合式應(yīng)用地理定位的方案

混合式應(yīng)用有兩種定位方案:

  1. 原生定位;
  2. 網(wǎng)頁(yè)定位;

原生定位使用GPS/北斗定位,網(wǎng)頁(yè)定位僅支持基站定位和WIFI定位兩種方式,自然優(yōu)先選型原生定位,但是,為了在一些影響GPS信號(hào)接收的地方提高精度,現(xiàn)在的第三方定位SDK大多又引入了后兩種方式作為輔助定位補(bǔ)充。高德和百度就是加入輔助定位的優(yōu)化過(guò)的定位方式,其中百度的會(huì)比高德的準(zhǔn)確一點(diǎn)。

Cordova封裝第三方原生定位SDK

IOS平臺(tái)都是通過(guò)系統(tǒng)SDK接口獲取的,因此所有App獲取定位及精度的能力是相同的,即使Google Maps、百度地圖、高德地圖這種專業(yè)地圖App也是如此;而Android平臺(tái)由于Google Service被閹割導(dǎo)致該系統(tǒng)SDK無(wú)法正常使用,國(guó)內(nèi)App通常是通過(guò)高德、百度等第三方SDK接口獲取定位信息,各定位能力和精度上會(huì)有些差異。所以,如果搜索Github上的源碼,發(fā)現(xiàn)大多Cordova定位插件只封裝第三方SDK的Android版本。如果IOS需要定位功能,則大多會(huì)選用apache的通用Corodva定位插件cordova-plugin-geolocation。換句話說(shuō),對(duì)于不少混合式應(yīng)用來(lái)說(shuō),使用如下的組合方案:

Android上第三方定位SDK封裝的Cordova插件 + IOS上使用cordova-plugin-geolocation。

在個(gè)人看來(lái),上述方案,cordova-plugin-geolocation只是調(diào)用了系統(tǒng)的SDK,并不會(huì)像國(guó)內(nèi)第三方SDK那樣添加了輔助定位的功能,總覺得有欠缺,更傾向于也接入第三方定位SDK,有部分網(wǎng)友也有我這種想法,所以也封裝了第三方定位IOS版插件,如:cordova-plugin-baidumaplocation。

對(duì)于這些兼容Android和IOS的Cordova插件又是如何考量的?我個(gè)人傾向于三個(gè)特點(diǎn):小、易用、新

  1. 如上述提到插件雖是較新的,但用的是百度地圖的庫(kù),比較臃腫,現(xiàn)在百度地圖把定位sdk獨(dú)立抽離了出來(lái)做成了百度定位sdk,所以如果它改成百度定位的庫(kù)我是比較樂意使用的。
  2. 百度和高德用誰(shuí)好我也掙扎了一段時(shí)間,最后選用高德,因?yàn)榭傮w上,高德的文檔相對(duì)較好,API也比較清晰簡(jiǎn)潔,對(duì)移動(dòng)端的支持也更友好些(如提供有移動(dòng)風(fēng)格的城市列表選擇組件)。
  3. 現(xiàn)有的高德定位插件,大多不維護(hù)了,使用的第三方庫(kù)都是2年或以上,比較舊,所以我造了個(gè)輪子:cordova-location-amap——但我也沒有維護(hù)了……

數(shù)據(jù)偏移之互聯(lián)網(wǎng)地圖坐標(biāo)系

有時(shí)候通過(guò)定位獲取的經(jīng)緯度并不是適用所有地圖的,如高德定位獲取到的經(jīng)緯度是不能在百度地圖上正確打點(diǎn)的,因?yàn)榈貓D使用了不同的坐標(biāo)系,常見的互聯(lián)網(wǎng)地圖坐標(biāo)系有下面三種:

WGS84(GPS)

國(guó)際標(biāo)準(zhǔn),一般從國(guó)際標(biāo)準(zhǔn)的GPS設(shè)備獲取的坐標(biāo)都是WGS84,以及國(guó)際地圖提供商使用的坐標(biāo)系。

GCJ02

中國(guó)標(biāo)準(zhǔn),國(guó)測(cè)局02年發(fā)布的坐標(biāo)系。又稱“火星坐標(biāo)”。在中國(guó),基于安全需要,必須至少使用“GCJ02”對(duì)地理位置進(jìn)行加偏處理,把真實(shí)的坐標(biāo)加密成虛假的坐標(biāo)。比如谷歌中國(guó)、高德、騰訊都在用這個(gè)坐標(biāo)系。

BD09

百度標(biāo)準(zhǔn)。 除了火星坐標(biāo)系統(tǒng),不同的地圖數(shù)據(jù)商也可能使用自己的坐標(biāo)系統(tǒng)。百度就在“GCJ02”的基礎(chǔ)上進(jìn)行二次加密。

所以跨地圖數(shù)據(jù)共享,一般有相應(yīng)的糾偏算法,如百度和高德的坐標(biāo)轉(zhuǎn)換:

/**
   * 高德坐標(biāo)轉(zhuǎn)百度
   * @param gg_lon 經(jīng)度
   * @param gg_lat 緯度
   */
  gaode2baidu(gg_lon, gg_lat): {
    longitude: number,
    latitude: number
  } {  
    if(gg_lon || gg_lat){
      return {
        longitude: gg_lon,
        latitude: gg_lat
      }
    }
    var X_PI = Math.PI * 3000.0 / 180.0;  
    var x = gg_lon, y = gg_lat;  
    var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);  
    var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);  
    var bd_lon = z * Math.cos(theta) + 0.0065;  
    var bd_lat = z * Math.sin(theta) + 0.006;  
    return {  
      longitude: parseFloat(bd_lon.toFixed(6)),
      latitude: parseFloat(bd_lat.toFixed(6))
    };  
  }  

  /**
   * 百度坐標(biāo)轉(zhuǎn)高德
   * @param bd_lon 經(jīng)度
   * @param bd_lat 緯度
   */
  baidu2gaode(bd_lon, bd_lat): {
    longitude: number,
    latitude: number
  } {  
    if(bd_lon || bd_lat){
      return {
        longitude: bd_lon,
        latitude: bd_lat
      }
    }
    var X_PI = Math.PI * 3000.0 / 180.0;  
    var x = bd_lon - 0.0065;  
    var y = bd_lat - 0.006;  
    var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);  
    var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);  
    var gg_lon = z * Math.cos(theta);  
    var gg_lat = z * Math.sin(theta);  
    return {  
      longitude: parseFloat(gg_lon.toFixed(6)),  
      latitude: parseFloat(gg_lat.toFixed(6))  
    }  
  }  

綜合上述知識(shí),可以得出使用單一的定位功能,也可以通過(guò)坐標(biāo)轉(zhuǎn)換算法兼容各種地圖服務(wù),也就是說(shuō)可以使用原生定位功能,結(jié)合網(wǎng)頁(yè)地圖實(shí)現(xiàn)地圖應(yīng)用,如我就是下面的方式使用:

    "cordova-location-amap": "^1.0.1",
    "cordova-plugin-android-permissions": "^1.0.0",

  <script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.3&key=3e1376d2e1aeff"></script>
  <!-- UI組件庫(kù) 1.0 -->
  <script src="http://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>

ionic中簡(jiǎn)單示例操作:

  1. 去地圖服務(wù)商申請(qǐng)?jiān)蚖eb版等key;
  2. 安裝基于對(duì)應(yīng)地圖服務(wù)商的Cordova插件,變量填入申請(qǐng)的key;
  3. 在index.html中添加上述js文件,然后在具體的某個(gè)頁(yè)面,如home.page.html中添加代碼(注意指定寬高,不然可能地圖出來(lái)了,但是卻看不多,自己還找半天):
  <div id="container" style="width:100%;height:100%">
  </div>
  1. home.page.ts添加初始化地圖代碼:
declare let AMap: any;
declare let Zepto: any;
declare let AMapUI: any; 
loadMap() {
    if(typeof (AMapUI) == "undefined" || typeof (Zepto) == "undefined"){
      return;
    }
    // 設(shè)置DomLibrary
    AMapUI.setDomLibrary(Zepto);
    if (typeof (AMap) != "undefined") {
      const map = new AMap.Map('container', {
        resizeEnable: true,
        zoom: 10,
        center: this.center
      });
      this.map = map;
      // 加載BasicControl,loadUI的路徑參數(shù)為模塊名中 'ui/' 之后的部分
      AMapUI.loadUI(['control/BasicControl'], (BasicControl)=> {
        // 縮放控件
        this.map.addControl(new BasicControl.Zoom({
            position: 'lt', //left top,左上角
            showZoomNum: true // 顯示zoom值
        }));
      });
    }
  }
  1. 調(diào)用原生定位功能:
cordova.plugins.aMapLocation.getCurrentPosition(this.configNative,
              (locate: {
                city: string,
                longitude: number,
                latitude: number
              }) => {
               console.log(locate);
              },
              e => {
               console.log(e);
              }
);

基本調(diào)用就這樣子了,省卻部分,僅提供主要代碼,如地圖key申請(qǐng)等請(qǐng)自行搜索。

定位方案不是唯一的,有的網(wǎng)頁(yè)定位的接口,會(huì)嘗試判斷是否安裝有自家的原生地圖應(yīng)用,有就借用其定位,沒有就使用網(wǎng)頁(yè)定位,有機(jī)會(huì)的也可以了解一下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容