Mapbox实现动态轨迹
最近工作中遇到了实现动态轨迹的需求,特在此记录一下:
- 基于Mapbox,Vue
- 使用Turf.js库计算地图相关数据
主要思路:
设置定时函数,从保存的数据列表
中添加新的坐标,并使用使用setData
更新地图。
先看定时函数:
let i = 0;
this.timer = setInterval(() => {
if (i < pointList.length) {
list.push(pointList[i]);
let timeData = turf.lineString(list, {
name: "line 1",
color: "#5ac58a",
});
map2D.getSource("FHTD_res").setData(timeData);
map2D.panTo(pointList[i]);
i++;
} else {
clearInterval(this.timer);
}
}, 100);
代码中的 pointList
为保存的数据列表:
注意:由于原始的轨迹数据一般为轨迹上的拐点的坐标(如图),按照原始数据动态效果不佳,因此需要对数据进行增密。
1.轨迹数据
- 使用
turf.lineString
方法将数据处理成线数据。
2.增密:使用turf.lineChunk
方法,其接收三个参数:线数据,切割长度,单位
- 使用
turf.length
方法计算出轨迹长度 - 根据不同长度计算出需要切割的长度
step = length / 1000 / 100;
- 使用
turf.lineChunk
方法将一个LineString分割成指定长度的块。如果LineString比分隔段长度短,则返回原始LineString。 - 最后遍历拿出所需要的数据放到数组
pointList
中,即为所需的数据列表
let line = turf.lineString(feature);
let length = turf.length(line, { units: "kilometers" }) * 1000;
let step = length / 1000 / 100;
let sliced = turf.lineChunk(line, step, { units: "miles" });
let pointList = [];
if (sliced.features.length) {
sliced.features.map((item) => {
item.geometry.coordinates.map((d) => {
pointList.push(d);
});
});
}
然后就是创建轨迹图层等操作了。
最后这里附上详细代码:
/***
* 参数格式
* feature(轨迹点坐标合集):[[x,y],[x1,y1],[x2,y2]]
* flyTo(轨迹开始点坐标):[x,y]
*/
getDynaTra(feature, flyTo) {
let list = [feature[0]];
//第一个点数据
let datas = turf.lineString(feature[0], {
name: "line 1",
color: "#5ac58a",
});
//将数据处理成线数据
let line = turf.lineString(feature);
//计算轨迹长度
let length = turf.length(line, { units: "kilometers" }) * 1000;
//计算步长
let step = length / 1000 / 100;
//对轨迹进行切割增密
let sliced = turf.lineChunk(line, step, { units: "miles" });
//
let pointList = [];
if (sliced.features.length) {
sliced.features.map((item) => {
item.geometry.coordinates.map((d) => {
pointList.push(d);
});
});
}
const map2D = GET_MAPBOX_MAP();
let source = map2D.getSource("FHTD_res");
if (source) {
map2D.removeLayer("FHTD_res");
map2D.removeSource("FHTD_res");
} else {
//
}
map2D.addSource("FHTD_res", {
type: "geojson",
data: datas,
});
map2D.addLayer({
id: "FHTD_res",
type: "line",
source: "FHTD_res",
layout: {
"line-join": "round",
"line-cap": "round",
},
paint: {
"line-color": ["get", "color"],
"line-width": 5,
},
});
map2D.jumpTo({ center: feature[0], zoom: 15 });
// map2D.setPitch(30);
// 设置定时函数,从保存的数据列表pointList中添加新的坐标,并使用使用setData()更新地图。
let i = 0;
this.timer = setInterval(() => {
if (i < pointList.length) {
list.push(pointList[i]);
let timeData = turf.lineString(list, {
name: "line 1",
color: "#5ac58a",
});
map2D.getSource("FHTD_res").setData(timeData);
map2D.panTo(pointList[i]);
i++;
} else {
clearInterval(this.timer);
}
}, 100);
flyTo &&
map2D.flyTo({
center: flyTo,
zoom: 15,
});
},
效果展示:
先看效果图!
动态轨迹