ReactNative实现地图导航

4,427 阅读4分钟

相关源码

同志们好,我又回归了,本来是想分享Flutter相关的内容,但是好久不写文章,感觉生疏了不少,不知道从何处下笔了,所有就把草稿箱躺了快一年的内容整理一下,分享分享。这篇文章是使用最简单的方式实现地图导航的需求,那就是通过唤起手机中的导航类软件进行导航,所以你想在应用内实现导航以及定制导航路线,那就可以到此为止了(如果有应用内导航需求或者线路规划需求的,留言,我可以写个底层的插件(android端,此时需要有个写ios底层合作的了)。 很多人都认为唤起导航软件进行导航,需要底层去写实现,其实大可不必,通过ReactNative自带的一些Api就可以实现我们想要的效果了。

Linking

Linking是RN中APP之间跳转交互的Api接口,并且能解析其中携带的参数数据。

  • getInitialURL 当我们的应用被其它应用注册唤醒,我们就可以通过它进行一些逻辑的处理,底层App唤醒的一些配置就不介绍了android 可前往developer.android.com/training/ap… 查看,ios自行搜索。这种需求在很多企业内多个应用直接经常会用到,在RN中使用很简单,只需要在首页组件的componentDidMount方法中注册就可以了,当然,官方文档中也有说明,在任何组件都可以获取到url参数。
componentDidMount() {
  Linking.getInitialURL().then((url) => {
    if (url) {
//可以根据url写跳转到相应的页面的逻辑和参数
      console.log('Initial url is: ' + url);
    }
  }).catch(err => console.error('An error occurred', err));
}
  • openURL 这个方法其实就是我们这篇文章的实现最重要的方法之一了,我们就可以通过他来打开第三方的App,下面列举几个常见的使用
Linking.openURL(url).catch(err => console.error('An error occurred', err));

//如打开浏览器访问
Linking.openURL("https://github.com/xiehui999")
//拨打电话
Linking.openURL("tel:1008611")
//发送短信
Linking.openURL("smsto:10086")

需要注意的是,在ios9.0及以上需要配置LSApplicationQueriesSchemes,否则调用无效。

  • canOpenURL 很多时候我们需要先判断判断设备上是否有已经安装的应用可以处理指定的 URL,该方法就可实现此功能,ios9需要配置LSApplicationQueriesSchemes,否则会一直返回false.

百度

  • url
baidumap://map/direction?origin=latlng:34.264642646862,108.95108518068|name:我家&destination=大雁塔&mode=driving&region=西安&output=html&src=webapp.baidu.openAPIdemo
//调起百度PC或Web地图,展示"西安市"从(lat:34.264642646862,lng:108.95108518068 )"我家""大雁塔"的驾车路线。

origin是必填项,后更导航起始点经纬度,name是导航地图显示的marker提示信息。destination是导航终点的经纬度或者名称。 mode指定导航路线的方法包括可选transit(公交)、driving(驾车)、walking(步行)和riding(骑行)(ios多个navigation)。根据自己的需求使用 其它具体参数可查看百度官方文档

高德

唤起高德地图规划线路的url前缀略有不同,基本内容还是一样的

//Android
amapuri://route/plan/?
//iOS
iosamap://path?

//后面追加内容
sourceApplication=test&slat=39.92848272&slon=116.39560823&sname=A&dlat=39.98848272&dlon=116.47560823&dname=B&dev=0&t=0

s开通的表示起点信息,不填默认当前位置,d开头的为终点信息,t为导航规划路线的方式 t = 0(驾车)= 1(公交)= 2(步行)= 3(骑行)= 4(火车)= 5(长途客车)

腾讯

qqmap://map/routeplan?type=drive&from=清华&fromcoord=39.994745,116.247282&to=怡和世家&tocoord=39.867192,116.493187&referer=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77

type路径规划方式,路线规划方式参数:分别为公交:bus ,驾车:drive ,步行:walk ,骑行:bike,from 开头的为起点信息,to开头的为终点信息,需要注意的是referer参数,官方文档说该参数为申请的腾讯地图的开发key.

通过上面的分析,我们就可以实现导航了,下面我们就简单的封装一下一个导航的工具类,包括三个判断是否安装相应地图软件的方法,和相应打开地图导航的方法

static isInstallAmap = () => {
        return new Promise((resolve, reject) => {
            Linking.canOpenURL(Platform.OS === "android" ? "amapuri://route/plan/" : "iosamap://path").then(supported => {
                resolve(supported)
            }).catch(resolve(false))
        })
    }
 /**
     * 打开高德地图导航
     * @param {String} data.sname - 起点名字.
     * @param {String|number} data.slon - 起点经度.
     * @param {String|number} data.slat - 起点纬度.
     * @param {String} data.dname - 终点名字.
     * @param {String|number} data.dlon - 终点经度.
     * @param {String|number} data.dlat - 终点纬度.
     * @param{Mode} data.mode 导航类型
     * @param data
     */
   static openAmap = (data = {}) => {
        let base = Platform.OS === "android" ? "amapuri://route/plan/?" : "iosamap://path?"
        return new Promise((resolve, reject) => {
            //起点经纬度不传,则自动将用户当前位置设为起点
            if (!data.dlat || !data.dlon) {
                resolve("需要终点经纬度")
            } else {

                if (data.slon && data.slat) {
                    base += `&slat=${data.slat}&slon=${data.slon}`
                }
                if (data.sname) {
                    base += `&sname=${data.sname}`
                }
                if (data.dname) {
                    base += `&dname=${data.dname}`
                }
                base += `&dlat=${data.dlat}&dlon=${data.dlon}&dev=0&t=${data.mode ? (data.mode.amap || 0) : 0}`
                Linking.openURL(base).then(res => {

                }).catch(err => {
                    reject("暂无安装高德地图")
                })
            }
        });
    }

上面我贴出了一个判断安装和一个唤起软件导航的方法,其它几种按此实现即可,当然我也把整理好的文件上传到GitHub了,具体细节可以前往RoutePlan文件,使用demo可前往RoutePlanExample文件,可以直接下载demo。