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()的回传数据
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。