开局两张图,剩下全靠吹
基于vue+百度地图的多车实时运动及轨迹追踪实现,共分为上下两篇,分别为上篇“心路历程篇”和下篇“上帝视角篇”,上篇是背景介绍和我实现过程中走的弯路,下篇是最终版的实现方案。其实并不存在上帝视角,只希望有一天,我们可以通过不断复盘,少走点弯路。
本篇是下篇,上帝视角篇。相关背景可查看上篇
不同于上篇内心戏满满,本篇内容过干,请自带水杯
剥离响应式数据和非响应式数据
除了页面上需要通过数据变化实时改变状态的数据,其他数据全部改为非响应式,直接在created生命周期中赋值即可。
created钩子函数是在vue完成数据拦截后调用的,所以这里定义的变量是不会自动被vue监听的。
例如websocket连接,缓存的车辆信息,定时器等变量,是不需要监听的,尤其是车辆信息,后端消息发送过来很快,如果每条消息过来引起车辆信息变化都触发vue的递归更新,是很慢的。这些信息均定义到created中。
created () {
this.socket = null // 实时socket连接
this.cachedCarArr = [] // 车辆信息
this.removeDelayed = 3000 // 预设3秒后车辆消失
this.carTimer = {
} // 车辆消失前的计数器
this.drawingLine = '' // 正在画实时轨迹的车
this.carLineAnimation = [] // 记录车的requestAnimationFrame id,便于后续取消
this.loopLineTimer = [] // 记录车的setTimeout id,便于后续取消
this.carLineAniInstances = {
} // 正在画实时轨迹的车的动画实例
this.trackCar = '' // 用于debug某个车
},
创建version变量来实现车辆列表的响应式
上面提到车辆信息存为了非响应式变量,那如何动态显示右侧的列表信息呢?这里有个变通的方法,在data()中定义一个top10List和一个version变量,当有新车过来的时候,version++,当一辆车消失的时候,version–。
同时监听version的变化,当version变化时,实时计算数组中前10个车,赋值给top10List。列表始终显示这10个车即可。
watch: {
version: {
handler () {
this.top10List = this.cachedCarArr
.filter((car) =>
car.trace.find((t) => t.status === 'drawing' || t.status === 'drawed')
)
.slice(0, 10)
}
}
}
设计存储车辆信息的数据结构
把车辆的运动看成一个状态机,每个点的状态都从’undraw’->‘drawing’->‘drawed’单向改变。接收信息时,车辆的初始状态为’undraw’
// 对于新车
const newCar = {
...car,
trace: [
{
lng: car.Longitude,
lat: car.Latitude,
rotation: car.PtcHeading,
speed: car.speed,
status: 'undraw',
timestamp: car.Timestamp
}
]
}
this.cachedCarArr.push(newCar)
this.drawCar(item)
this.version++
// 对于已有的车
this.cachedCarArr = this.cachedCarArr.map((item) => {
if (item.id === key) {
item.trace.push({
lng: car.Longitude,
lat: car.Latitude,
rotation: car.PtcHeading,
speed: car.speed,
status: 'undraw',
timestamp: car.Timestamp
})
}
return item
})
多车实时运动
1. 画车
const pointT = transform({
lng: car.trace[0].lng,