由于本人公司的业务很多是基于车辆报警,定位,货运的,所以平时pc端地图接触的比较多,目前主要以高德地图为主,百度地图为辅,百度地图一般也不用,只是业务涉及到地图切换的时候会两个地图都用。此外接手项目的时候发现项目里还用到了vue-baidu和vue-amap这两个插件,个人感觉也不推荐使用,一个是感觉使用起来并没有方便多少,而且插件内部时常会有一些小坑,会增加开发和维护的成本。
对于我们系统来说,业务的核心离不开GPS点。GPS点坐标有3种类型,WGS-84,GCJ-02,BD-09,分别对应设备,高德地图,百度地图使用的坐标类型,这三种可以互相转化,代码网上搜搜很多。在车辆物流的业务开发中,很多时候都需要对GPS列表进行处理。比如如下结构
[{lng:xxxx,lat:xxxx,direction:xxxxx},{lng:xxxxx,lat:xxxxxx,direction:xxxxx}]
1.虚拟GPS: 由于设备上报的GPS点不是连续的,通常会有一定的时间间隔,这会使得两个点中间产生一定的距离,假如我们要实现一个小车平滑移动的需求,高德和百度都要能兼容,一开始想到的肯定是写一个定时器,去每过一段时间改变小车的坐标,但是由于坐标不是连续的,所以会导致小车出现'瞬移'的情况,所以我们就需要在没两个坐标点中间人为的构造出一系列点来模拟中间的运动过程,使其尽可能平滑。
思路
graph TD
三维坐标系 --> 二维坐标系 --> 划分成n等分 -->求出每个点的平面二维坐标 -->转化成三维坐标
具体使用的api:lnglatToPixel,pixelToLngLat,相关api介绍如下。
这样我们就在2个真实的GPS点中间人为的构造出了一系列的点,至于每两个点中间大概要构造多少个点,看具体业务需求,能满足业务需求即可。这样就能实现小车的平滑移动了。
当然虚拟GPS的业务场景还有其他的,比如我们需要在一整段路径上去用一个多边形框选一段路径,地图相关的业务场景可能会遇到这类需求,初步的方案就是对地图上每一个路径上的点进行遍历,利用高德地图数学类api去提取出位于区域内的点(这个不难做到),但是由于两个点中间存在一定的距离,所以必然会导致用户框选的区域范围要大于实际截取的范围,使用虚拟GPS就能完美解决这个问题,只要把两点间的分割精度给他增大就可以了。
2、地图切换导致代码结构混乱不堪,业务逻辑复杂,代码可读性差:
假如产品经理要求在高德里的功能需要在同事在百度地图中支持怎么办?是不是感到十分的头疼。
必然会出现很多的if(mapType ==='gaode' xxxxxxxx else xxxxxxxx)代码也写得很丑陋。。
其实核心说的直白一点就是 当地图是高德的时候,调用高德的xxxx方法,百度的时候,调用百度的xxxx方法,很多时候两个方法的目的是一样的,但是所用的api不同,那其实用两个地图类就刚好合适
class Amap{ drawLine(){ } drawPoint(){ }
class Bmap{ drawLine(){ } drawPoint(){ }
调用的时候根据maptype分别去调用各自的方法就可以了,这样应该比刚刚那样更清晰一点,但是这样还是避免不了写 “if(maptype ==='gaode')”类似的代码,那一步能不能也自动处理呢,写代码的时候只要写this.drawLine(),这样是不是更好,思考过后,发现用Proxy刚好完美实现。
new Proxy ({ Amap:(实例) Bmap },(target,xxxx)=>{ return target[this.maptype].xxxxx })
代码记不太清了,大致就是使用一个代理对象“mapcontent”去进行托管,当访问mapcontent.drawLine的时候Proxy里的拦截器起作用,自动访问当前地图种类下的地图类中对应的方法。这样代码结构就十分的清晰了。而且这样还有一个好处,两个地图中难免会用到一些公共的方法,直接放在一个基类中,让两个地图类去继承就OK了,代码会优雅很多。 有什么地图相关的业务需求,欢迎讨论!