React Native 高德地圖選址

預覽

React Native高德地圖SDK插件分析

  • react-native-smart-amap
    這個庫比較完美實現了地圖選址功能,但是作者好像不再維護了,所以慎用。
  • react-native-amap3d
    這個庫做的比較好,功能比較齊全,但是經過分析后,很難實現我們想要的功能。而且作者也建議使用網頁實現此類功能。
  • react-native-amap-geolocation
    react-native-amap3d 作者將定位功能抽出來,針對的是使用高德地圖進行高精度定位。感謝作者!

實現思路

  • 根據react-native-amap3d作者的建議,我們使用網頁實現主體界面。
  • 使用react-native-amap-geolocation進行高精度定位

申請高德地圖key

  • 在高德地圖管理控制臺申請Android、iOS和web端key。

web端實現

  • 使用高德地圖選址組件,請按照高德地圖說明申請web端key
  • 添加本地html代碼
  • map.html
<!doctype html>
<html>
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="apple-mobile-web-app-capable" content="yes" />
   <meta name="apple-mobile-web-app-status-bar-style" content="black" />
   <title>地理位置</title>
   <style>
       body{
           position: absolute;
           top: 0;
           bottom: 0;
           left: 0;
           right: 0;
           margin: 0;
       }
       iframe{
           width: 99%;
           height: 98%;
       }

   </style>
</head>
<body>
<iframe id="container" src=''></iframe>
<script>
       (function(){
           var iframe = document.getElementById('container').contentWindow;
           document.getElementById('container').onload = function(){
               iframe.postMessage('hello','https://m.amap.com/picker/');
           };
           window.addEventListener("message", function(e){
               window.postMessage(JSON.stringify({
                   name: e.data.name,
                   location: e.data.location,
                   address: e.data.address
               }))
           }, false);
       }())
   </script>
</body>
</html>
  • 需要注意的一點就是,由于React-Native WebView加載本地html文件問題,map.html文件需要分兩個目錄進行存放,iOS可以直接放在項目任何目錄下(如:項目根目錄)引用即可,而android必須放在android assets文件下才可以引用。
  • 使用window.postMessage() 將位置選取信息回傳給WebView
  • 如圖:


    android文件存儲目錄

React Native端實現

//  獲取定位權限,由于我寫界面的時候,還需要其他權限,這邊我使用的是多權限申請方式,定位的單個申請是沒問題的。如果覺得別扭,可以自行修改。
async componentDidMount () {
    await init({
      ios: IOS_MAP_KEY, // iOS key
      android: ANDROID_MAP_KEY // android key
    })
    if (!IS_IOS) {
        try {
          const permissions = [
            PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION
          ]
          // 返回得是對象類型
          const granteds = await PermissionsAndroid.requestMultiple(permissions)
          if (granteds['android.permission.ACCESS_COARSE_LOCATION'] !== 'granted') {
            ToastAndroid.show('請開通定位權限,否則應用定位功能無法正常使用!', ToastAndroid.SHORT)
          } else {
            this.getCurrentPosition()
          }
        } catch (e) {
          ToastAndroid.show('定位權限獲取異常', ToastAndroid.SHORT)
        }
    } else {
      this.getCurrentPosition()
    }
  }

// 獲取定位信息
getCurrentPosition () {
    Geolocation.getCurrentPosition(({ location }) => {
      this.setState({
        lat: location.latitude,
        lng: Math.abs(location.longitude), //  國內獲取的是一個負值。這里需要注意一下,是否考慮使用{lng:-location.longitude} 請自行驗證
        positionGetError: false
      })
    }, () => {
      this.setState({
        positionGetError: true
      })
    }, {
      timeout: 8
    })
  }
  • 使用WebView加載網頁
// WEB_CLIENT web端key值
    <WebView
        bounces={false}
        domStorageEnabled={false}
        javaScriptEnabled
        useWebKit
        injectedJavaScript={`document.getElementById("container").src="https://m.amap.com/picker/?center=${this.state.lng},${this.state.lat}&zoom=18&key=${WEB_CLIENT}&keywords=景區,超市,小區"`}
        onMessage={(e) => {
          console.log('data', e.nativeEvent.data)
        }}
        mixedContentMode={'always'}
        renderError={() => this._renderWebViewError()}
        source={IS_IOS ? require('../htmls/map.html') : { uri: 'file:///android_asset/htmls/map.html' }}
      />
  • 注意:添加useWebKit,否則iOS可能會出現問題
  • 從代碼中我們可以看出,我們使用injectedJavaScript對web端注入了一段javascript代碼,目的是將我們的位置信息注入,并且改變web端iframe的src地址。
  • onMessage獲取web端postMessage()的回傳數據
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。