效果:
// 轨迹线
export const MAP_PATH_LINE = (values, layerId) => {// 箭头-右var svgXML = `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> <path d="M529.6128 512L239.9232 222.4128 384.7168 77.5168 819.2 512 384.7168 946.4832 239.9232 801.5872z" p-id="9085" fill="#ffffff"></path> </svg>`;//给图片对象写入base64编码的svg流var svgBase64 = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgXML)));let arrowIcon = new Image(20, 20);arrowIcon.src = svgBase64;arrowIcon.onload = function () {map.addImage('arrowIcon', arrowIcon);setRouteData();// map.loadImage('./car.png', function (error, carIcon) {// if (carIcon) {// map.addImage('carIcon', carIcon);// setRouteData();// }// });};var isPlay = true;var counter = 0;var steps = 0;let aLength = 0;let newRouteGeoJson;var routeGeoJson = values;var realRouteGeoJson = {type: 'FeatureCollection',features: [{type: 'Feature',geometry: {type: 'LineString',coordinates: [],},},],};var animatePointGeoJson = {type: 'FeatureCollection',features: [{type: 'Feature',properties: {},geometry: {type: 'Point',coordinates: [],},},],};// 获取轨迹边界var bbox = turf.bbox(routeGeoJson);map.fitBounds([[Number(bbox[0]), Number(bbox[1])],[Number(bbox[2]), Number(bbox[3])],],{padding: { top: 100, bottom: 100, left: 100, right: 100 },maxZoom: 16,},);// 获取轨迹数据function setRouteData() {animatePointGeoJson.features[0].geometry.coordinates = routeGeoJson.features[0].geometry.coordinates[0];aLength = routeGeoJson.features[0].geometry.coordinates.length;newRouteGeoJson = resetRoute(routeGeoJson.features[0], 1000, 'kilometers');steps = newRouteGeoJson.geometry.coordinates.length;addRouteBboxLayer(); // 添加轨迹边界图层addRoutelayer(); // 添加轨迹线图层// addRealRouteSource(); // 添加实时轨迹线图层addArrowlayer(); // 添加箭头图层// addAnimatePointSource(); // 添加动态点图层}// 添加轨迹边界图层function addRouteBboxLayer() {map.addLayer({id: 'routeBboxLayer',type: 'line',source: {type: 'geojson',data: turf.bboxPolygon(bbox),},paint: {'line-color': '#fbc219','line-width': 3,'line-dasharray': [1, 1],'line-offset': -10,},});}// 添加轨迹线图层function addRoutelayer() {map.addLayer({id: 'routeLayer',type: 'line',source: {type: 'geojson',lineMetrics: true,data: routeGeoJson,},paint: {'line-width': 10,'line-opacity': 1,'line-color': '#009EFF',},});}// 添加实时轨迹线function addRealRouteSource() {map.addLayer({id: 'realRouteLayer',type: 'line',source: {type: 'geojson',lineMetrics: true,data: realRouteGeoJson,},paint: {'line-width': 10,'line-opacity': 1,'line-color': '#FF9900',},});}// 添加箭头图层function addArrowlayer() {map.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.5,},});}// 添加动态点图层function addAnimatePointSource() {map.addLayer({id: 'animatePointLayer',type: 'symbol',source: {type: 'geojson',data: animatePointGeoJson,},layout: {'icon-image': 'carIcon','icon-size': 0.5,'icon-rotate': ['get', 'bearing'],'icon-rotation-alignment': 'map','icon-allow-overlap': true,'icon-ignore-placement': true,},});animate();}function 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)) - 90;animatePointGeoJson.features[0].geometry.coordinates = newRouteGeoJson.geometry.coordinates[counter];realRouteGeoJson.features[0].geometry.coordinates.push(animatePointGeoJson.features[0].geometry.coordinates);map.getSource('animatePointLayer').setData(animatePointGeoJson);map.getSource('realRouteLayer').setData(realRouteGeoJson);if (isPlay) {requestAnimationFrame(animate);}counter = counter + 1;}function 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: 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;}function 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: units,});rings.push(pnt.geometry.coordinates);}if (leftLength > 0) {rings.push(to.geometry.coordinates);}return rings;}
};
清除数据代码
// 清除轨迹
export const ClearTrackMap = () => {if (map?.hasImage('arrowIcon')) map?.removeImage('arrowIcon');if (map?.hasImage('carIcon')) map?.removeImage('carIcon');if (map.getLayer('routeBboxLayer')) map.removeLayer('routeBboxLayer');if (map.getSource('routeBboxLayer')) map.removeSource('routeBboxLayer');if (map.getLayer('routeLayer')) map.removeLayer('routeLayer');if (map.getSource('routeLayer')) map.removeSource('routeLayer');if (map.getLayer('realRouteLayer')) map.removeLayer('realRouteLayer');if (map.getSource('realRouteLayer')) map.removeSource('realRouteLayer');if (map.getLayer('arrowLayer')) map.removeLayer('arrowLayer');if (map.getSource('arrowLayer')) map.removeSource('arrowLayer');if (map.getLayer('animatePointLayer')) map.removeLayer('animatePointLayer');if (map.getSource('animatePointLayer')) map.removeSource('animatePointLayer');REMOVE_LAYER('vectorDataID');REMOVE_LAYER(`feature_0.1`);
};