16.gis车辆轨迹回放之mapbox-gl

数据准备

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
}

结果展示

16.gis车辆轨迹回放之mapbox-gl_第1张图片

你可能感兴趣的:(javascript,arcgis)