routeGeoJson轨迹数据
svgXML道路箭头
newRouteGeoJson根据速度生成新的轨迹点数组
realRouteGeoJson车辆经过后的轨迹线
animatePointGeoJson车辆位置
var svgXML =
`
`
//给图片对象写入base64编码的svg流
var svgBase64 = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgXML)));
var isPlay = false
var counter = 0
var steps = 0
let aLength = 0;
var newRouteGeoJson;
var routeGeoJson = {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': [[108,34],[108,35],[109,35]]
}
}]
}
var realRouteGeoJson = {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': []
}
}]
}
var animatePointGeoJson = {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': []
}
}]
}
通过调用下列方法可实现车辆出发、暂停、继续、返回、清除所有
// 开始
export const startClick=async()=> {
isPlay=false
if (!isPlay) {
clearAllLayers()
await initCarAndLine();
isPlay = true
animate()
}
}
// 暂停
export const pauseClick=()=> {
isPlay = false
animate()
}
// 继续
export const goOnClick=async()=> {
if (!isPlay) {
isPlay = true
animate()
}
}
// 返回
export const stopClick=()=> {
isPlay = false
counter = 0
animate()
}
// 清除相关图层
export const clearAllLayers=()=> {
isPlay = false
counter = 0
animate()
removeLayerAndSourceById("routeLayer");
removeLayerAndSourceById("realRouteLayer");
removeLayerAndSourceById("arrowLayer");
removeLayerAndSourceById("animatePointLayer");
removeImageById("arrowIcon");
removeImageById("carIcon");
}
初始化图标及重新获取轨迹点数据,在一定范围内开始循环调用改变车辆位置、方向以及轨迹
export const initCarAndLine =(param)=>{
let arrowIcon = new Image(20, 20)
arrowIcon.src = svgBase64
arrowIcon.onload = function () {
window.$mapbox.addImage('arrowIcon', arrowIcon)
window.$mapbox.loadImage(new URL("/car.png", import.meta.url).href, function (error, carIcon) {
if (carIcon) {
window.$mapbox.addImage('carIcon', carIcon);
setRouteData(param)
}
})
}
}
export const setRouteData=async()=> {
routeGeoJson.features[0].geometry.coordinates=[]
cardatas.forEach((item)=>{
routeGeoJson.features[0].geometry.coordinates.push([item.JD,item.WD]);
})
// 开始
animatePointGeoJson.features[0].geometry.coordinates = routeGeoJson.features[0].geometry.coordinates[0]
animatePointGeoJson.features[0].properties=param
aLength = routeGeoJson.features[0].geometry.coordinates.length;
newRouteGeoJson = resetRoute(routeGeoJson.features[0], 3000, {units: 'kilometers'})
steps = newRouteGeoJson.geometry.coordinates.length
addRoutelayer() // 添加轨迹线图层
addRealRouteSource() // 添加实时轨迹线图层
addArrowlayer() // 添加箭头图层
addAnimatePointSource() // 添加动态点图层
var geojson= window.$mapbox.getSource('routeLayer')._data;
const bound = turf.bbox(geojson)
const min = window.$mapbox.project([bound[0], bound[1]])
const max = window.$mapbox.project([bound[2], bound[3]])
window.$mapbox.fitScreenCoordinates(min, max, window.$mapbox.getBearing())
}
// 添加轨迹线图层
export const addRoutelayer=() =>{
window.$mapbox.addLayer({
'id': 'routeLayer',
'type': 'line',
'source': {
'type': 'geojson',
'lineMetrics': true,
'data': routeGeoJson
},
'paint': {
'line-width': 6,
'line-opacity': 1,
'line-color': '#A01F05'
},
'layout':{
'line-join':'round'
}
});
}
// 添加实时轨迹线
export const addRealRouteSource=()=> {
window.$mapbox.addLayer({
'id': 'realRouteLayer',
'type': 'line',
'source': {
'type': 'geojson',
'lineMetrics': true,
'data': realRouteGeoJson
},
'paint': {
'line-width': 6,
'line-opacity': 1,
'line-color': '#009EFF'
},
'layout':{
'line-join':'round'
}
});
}
// 添加箭头图层
export const addArrowlayer=() =>{
window.$mapbox.addLayer({
'id': 'arrowLayer',
'type': 'symbol',
'source': {
'type': 'geojson',
'data': routeGeoJson //轨迹geojson格式数据
},
'layout': {
'symbol-placement': 'line',
'symbol-spacing':50, // 图标间隔,默认为250
'icon-image': 'arrowIcon', //箭头图标
'icon-size': 0.4
}
});
}
// 添加动态点图层
export const addAnimatePointSource=() =>{
window.$mapbox.addLayer({
'id': 'animatePointLayer',
'type': 'symbol',
'source': {
'type': 'geojson',
'data': animatePointGeoJson
},
'layout': {
'icon-image': 'carIcon',
'icon-size': 0.8,
'icon-rotate': ['get', 'bearing'],
'icon-rotation-alignment': 'map',
'icon-allow-overlap': true,
'icon-ignore-placement': true,
}
});
window.$mapbox.on('click','animatePointLayer', function (e) {
store.commit('getLayerInfo', e.features[0])
});
animate()
}
export const animate=()=> {
if (counter >= steps) {
return;
}
var startPnt, endPnt
if (counter == 0) {
realRouteGeoJson.features[0].geometry.coordinates = []
startPnt = newRouteGeoJson.geometry.coordinates[counter]
endPnt = newRouteGeoJson.geometry.coordinates[counter + 1]
} else if (counter !== 0) {
startPnt = newRouteGeoJson.geometry.coordinates[counter - 1]
endPnt = newRouteGeoJson.geometry.coordinates[counter]
}
animatePointGeoJson.features[0].properties.bearing = turf.bearing(
turf.point(startPnt),
turf.point(endPnt)
) ;
animatePointGeoJson.features[0].geometry.coordinates = newRouteGeoJson.geometry.coordinates[counter];
realRouteGeoJson.features[0].geometry.coordinates.push(animatePointGeoJson.features[0].geometry.coordinates)
if(getSourceById("animatePointLayer")){
// 更新位置
window.$mapbox.getSource('animatePointLayer').setData(animatePointGeoJson);
}
if(getSourceById("realRouteLayer")){
window.$mapbox.getSource('realRouteLayer').setData(realRouteGeoJson);}
if (isPlay) {
requestAnimationFrame(animate)
}
counter = counter + 1;
}
export const resetRoute=(route, nstep, units) =>{
var newroute = {
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': []
}
}
var lineDistance = turf.lineDistance(route);
var nDistance = lineDistance / nstep;
for (let i = 0; i < aLength - 1; i++) {
var from = turf.point(route.geometry.coordinates[i]);
var to = turf.point(route.geometry.coordinates[i + 1]);
let lDistance = turf.distance(from, to, units);
if (i == 0) {
newroute.geometry.coordinates.push(route.geometry.coordinates[0])
}
if (lDistance > nDistance) {
let rings = lineMore(from, to, lDistance, nDistance, units)
newroute.geometry.coordinates = newroute.geometry.coordinates.concat(rings)
} else {
newroute.geometry.coordinates.push(route.geometry.coordinates[i + 1])
}
}
return newroute
}
// 按速度生成更多点
export const lineMore=(from, to, distance, splitLength, units) =>{
var step = parseInt(distance / splitLength)
var leftLength = distance - step * splitLength
var rings = []
var route = turf.lineString([from.geometry.coordinates, to.geometry.coordinates])
for (let i = 1; i <= step; i++) {
let nlength = i * splitLength
let pnt = turf.along(route, nlength, units);
rings.push(pnt.geometry.coordinates)
}
if (leftLength > 0) {
rings.push(to.geometry.coordinates)
}
return rings
}