本文已参与「新人创作礼」活动,一起开启掘金创作之路。
微信小程序地图导航实现思路
前端布局设计
合理布局解决地图组件层级高于 WebView 层级问题:我们尝试使用 Android 设备,开启开发者选项中 Show layout bounds(显示布局格子)选项,再进入小程序,可以查看到前端布局。 Android 开发者选项中 show layout bounds 是一个很常用的功能,开启后可以知道界面上哪部分是用 Native 实现、哪部分是用 Hybrid web 实现。
小程序的 map 组件是使用 Native 来实现的,它并不是一个 WebView 容器,而原生组件的特性是它总会覆盖在 WebView 组件之上。
利用 page 页面对 map 组件采用绝对定位、高度自适应的方法,实现 WebView 组件不被地图组件遮盖、地图组件又可随 WebView 组件尺寸,动态改变高度。
此外,当用户点击地图上标记的位置时,需求是要以弹窗形式询问用户下一步操作。
由于开发上无法实现在原生的 map 组件上弹出 WebView 蒙层,可以采用如下的方式实现:即,当需要在 map 组件之上弹出蒙层时:
- 隐藏 map 组件和相关的不需要的 WebView 元素(比如顶部的分类条和地步的商户列表)。
- 使用一张以中心点定位的地图图片来作为背景元素。
- 在该背景图片上覆盖 WebView 弹窗。
- 等用户操作结束后再隐藏图片,恢复 map 和相关组件的展示。
其实,解决该问题的更好的办法,是通过使用小程序的画布 Canvas 组件来实现,因为画布也是使用 Native 组件来实现的。 具体方式是:先使用 Canvas 绘制一个蒙层,再在 Canvas 蒙层上绘制 Canvas 弹窗。
地图上地点位置获取
数据获取部分主要介绍商户经地理位置的采集。商户经纬度采集我们采用了高德开放平台,输入商户名,获取其坐标点。
用户位置获取:用户进入导航页后会请求获取用户地理位置。获得用户授权后,会使用 wx.getLocation API 获取用户位置。
注意,该 API 默认 type 取值为 WGS84。为了在地图上显示在正确的位置,则 type 需要设为 gcj02 ,也就是我们平常所说的「火星坐标系」(官方称「地形图非线性保密处理算法」)。
关于 WGS-84 和 GCJ-02,我们需要了解的是:GPS 全球定位系统的经纬度坐标使用标准 WGS-84,换到使用 GCJ-02 的中国网路图上时,会造成距离在 500m 左右不等的显著偏移。
更多信息,可以在网络上搜寻有关「中华人民共和国测绘限制」的资料。
两点间距离获取:两点间距离使用腾讯地图的距离计算 API 得出。调用距离获取和线路导航功能接口,都需要事先获取调用 key 才可以使用。
导航路线点获取:由于商户的地理位置信息是使用高德地图采集到的。同时,高德地图也推出了自己的微信小程序 SDK,所以路线规划我们引入了高德地图的小程序版 SDK 来求取。 将获取到的路线数组,设置为 map 组件 polyline 的数据源即可。
小程序页面跳转规划
在小程序中,所有页面的路由全部由框架进行管理。
而小程序有 5 层页面栈的限制,即如果在页面切换过程中,页面栈内页面数量超过 5,小程序将无法再进行跳转,或者发生一些意外行为。
所以我们在开发小程序时,一定要规划好小程序的页面栈,或结合产品进行跳转优化,或者从根源上精简需求,以期开发出更实用更健壮的小程序。
此时,在地图页只允许进行两种操作:
- 第一种是按左上角,上一层「商户详情」页面,在详情页则只能继续返回上一层或者再次进入导航页,不会出现爆栈的情况。
- 第二种方法,是通过判断页面栈中是否存在地图页。存在的话,则返导航页显示回到地图控件,用户点击后将直接调用 wx.navigateBack 加 delta 参数,直接跳回多级到地图页。
另需注意的是,并不是所有导航 API 都可以携带参数,设计路由时也要同时考虑参数传递问题。