开局两张图,剩下全靠吹
基于vue+百度地图的多车实时运动及轨迹追踪实现,共分为上下两篇,分别为上篇“心路历程篇”和下篇“上帝视角篇”,上篇是背景介绍和我实现过程中走的弯路,下篇是最终版的实现方案。其实并不存在上帝视角,只希望有一天,我们可以通过不断复盘,少走点弯路。
本篇是上篇,心路历程篇
项目背景
此处省略一万字,交给产品经理。到我这边接到的需求其实就是实现车辆实时移动,并进行轨迹追踪。
不,其实我接到的是一份队友跑路待整改的代码!
看我如何把图一变成图二的效果,嘻嘻【请忽略我图二录屏时右下角不小心保留的浮层图】
老代码思路
看了一眼这个素未谋面的队友的代码,其实他原来代码结构还是比较清晰的。
可以保留的设计:
1. websocket方式接收数据。因为车辆数据会源源不断产生,前端定时拉取不可取,所以采用了websocket方式接收数据。
2. 通过id标记一个车的覆盖物(marker和label),方便后面删除
3. 嗯,我努力想想,一定会有3的
需要改进的点
1. 车辆是跳动前进的,很不真实
2. 背景过于朴素
需要增加的功能
1. 车辆需要显示实时的速度
2. 需要加一个列表,实时更新当前在跑的车辆信息,限制显示前10辆车
3. 增加轨迹线功能,实时追踪该车辆的前进轨迹
车辆跳动的原因
原来的实现思路是:在每次接收数据的时候,清空该车所画的覆盖物(车和label),并用新的经纬度数据重新画覆盖物,车辆是从第一点直接到了另一个点,所以看起来就像是跳过去的。
改造步骤
以下是项目过程中的一些最终被抛弃的思路,想直接看最终方案的,请移步上帝视角篇
1. 重画=》设置新位置
我的第一反应是移动位置总比重新画要快吧,所以首先从改造数据结构入手,把后端发过来的轨迹消息按照车辆归类记录下来,设置初始状态为’undraw’,并在每次来一个新消息的时候,拿所有状态为’undraw’的点去移动,移动开始前把状态设为’drawing’, 移动结束后把状态设为’drawed’(此处先埋一个坑,坑1)。
自认为看起来很完美,撸完后发现,设置车辆位置的时候,经常提示这个车的覆盖物还不存在。可是我明明是画完车再移动它的位置的呀,难道画车这个步骤的异步的?(此时的我还傻傻的忽视了那个大大的坐标转换函数,sigh)
异步就异步吧,再加两个状态!如果是这辆车第一个点,则画之前标记为’marking’,画完后标记为’marked’,只有当第一个点的状态为’marked’后,才进行后面的移动。终于不报错了,但我期待的效果是半点都没有,似乎还更槽糕了。(继续埋坑,坑2)
2. 平滑效果
开始全网搜如何让车辆平滑移动:
a ) 百度地图自有的轨迹动画api参考4,更适用于已知整个轨迹,并在指定的时间内回放完成。
b) 前辈写的基于百度地图的多图标平滑移动方案参考2,主要思路是补点,根据两个点之间距离来计算要补多少个点,并用setInterval去定时移动到下一个点。但其中用到的计算距离的函数适用于百度地图jsapi v2版本,我们用的是百度地图js webgl v1版本,要注意一下不能直接使用。
c) 其他的基本上也是补点的思路,就是计算距离的函数不太一样,如参考3,是从其他文章里了解到的turfjs包,里面有很多跟地图和距离相关的工具函数,这里记录一下,以后可能用的到。
到这里基本确定使用补点的思路。最开始因为方案b)不能直接使用,采用了方案c)里的函数,发现车辆几乎都没动(其实是车已经飞走了,年少无知的我以为车没动),就把距离打印出来看了一下,看到两点之间的距离是0.00099km,想着莫非太近了,所以看起来不动?又或者是这个库的距离算起来不准,不死心地跑去百度那边试了一下,虽然大了那么一丢丢,但绝对值还是很小。
var from = turf.point([113.27720709322817, 23.351992192427748]);
var to = turf.point([113.2772194870973, 23.352001006312186]);
var options = {
units: 'miles'};
turf.distance(from, to, options);
0.0009944611081986045
这时打算先取个巧,不计算距离了,自己先固定一个分割的点数看看效果。观察后端发过来的消息,大概每个车每秒有2条数据,按照60fps来算,设置了两点之间共分成30个点来画,又信心满满地试了一把。
这时发现了一个异常,移动的时候,从一跳一跳变成了一顿一顿,这时眼瞎的我终于发现了那个不起眼的百度坐标转换函数,它不仅要调用百度地图api来拿到转换后的结果,而且限制了每次最多只能转换10个点,而我家的破网为了让我按时下班,一到晚上就卡得不行,所以这个问题