arcgis for js4.x实现车辆轨迹回放
实现效果
代码如下
const mapView = Global.map
let trackLayer = new GraphicsLayer()
let moveLayer = new GraphicsLayer()
mapView.map.addMany([trackLayer, moveLayer, pointLayer, lineLayer, areaLayer])
let carPaths: any[] = []
let startingPoint = {}
let moveCarGra: any = null
let moving: any
let startNum = 0
let endNum = 0
const playPaths = () => {
carPaths = [
[120.32392468264094, 31.558573467415158],
[120.32276596834647, 31.56334552204247],
[120.32731499483586, 31.56557605388105],
[120.3302761535884, 31.561700013542776],
[120.33864464571506, 31.561590311943927],
[120.34182038118878, 31.563107839275233],
[120.33875193407567, 31.564863020815636],
[120.33699240496185, 31.566307364182478],
[120.33643450548675, 31.566965538550427],
[120.33306565096395, 31.569945547694143],
[120.32993283083445, 31.56762370827309],
[120.3290101509333, 31.56769683795552],
[120.3267141800165, 31.566490190861764]
]
const polylineGraphic = new Graphic({
geometry: new Polyline({
paths: carPaths,
// spatialReference: mapView.spatialReference
spatialReference: { wkid: 4326 }
}),
symbol: {
type: 'simple-line', // autocasts as new SimpleLineSymbol
color: '#0073f3',
width: 5,
cap: 'round',
join: 'round'
} as any
})
// 将绘制的图形添加到view
trackLayer.add(polylineGraphic)
// 初始化车辆
const modelCar = initModelCar()
moveCarGra = new Graphic({
geometry: startingPoint,
symbol: modelCar
})
moveLayer.add(moveCarGra)
mapView.when(
() => {
// 地图加载完成
setTimeout(() => {
mapView.goTo({
// 视角切换动画
center: [carPaths[0][0], carPaths[0][1]], //终点坐标
heading: 360, // 面向正南
z: 10000,
tilt: 40, //视图角度cos
zoom: 18 //放大等级
})
}, 1000)
},
(error: any) => {
console.error(error)
}
)
}
// 开始播放
const start = () => {
if (moving !== undefined) {
clearInterval(moving) //清除移动
}
moveCarGra.geometry = startingPoint
move(0, 1)
}
// 车辆暂停
const stopMove = () => {
clearInterval(moving)
}
// 车辆继续(未点击开始前,应禁用“继续”按钮)
const goOn = () => {
if (moving !== undefined) {
clearInterval(moving) // 清除移动
}
move(startNum, endNum)
}
// 车辆返回
const back = () => {
if (moving !== undefined) {
clearInterval(moving) // 清除移动
}
moveLayer.removeAll()
resetCar(carPaths)
mapView.goTo(carPaths)
}
const resetCar = (carPaths: any) => {
const polylineGraphic = new Graphic({
geometry: new Polyline({
paths: carPaths,
// spatialReference: mapView.spatialReference
spatialReference: { wkid: 4326 }
}),
symbol: {
type: 'simple-line', // autocasts as new SimpleLineSymbol
color: '#0073f3',
width: 5,
cap: 'round',
join: 'round'
} as any
})
// 将绘制的图形添加到view
trackLayer.add(polylineGraphic)
// 初始化车辆
const modelCar = initModelCar()
moveCarGra = new Graphic({
geometry: startingPoint,
symbol: modelCar
})
moveLayer.add(moveCarGra)
}
const move = (start: number, end: number) => {
let x1 = carPaths[start][0]
let y1 = carPaths[start][1]
let x2 = carPaths[end][0]
let y2 = carPaths[end][1]
//斜率
let p = (y2 - y1) / (x2 - x1)
//速度
let v = 0.00008 // 过小会导致线路偏移
moving = setInterval(() => {
moveLayer.removeAll()
startNum = start
endNum = end
// 分别计算 x,y轴的方向和速度
if (Math.abs(p) === Number.POSITIVE_INFINITY) {
// 垂直的时候斜率无穷大
const point = moveCarGra.geometry
if (y2 > y1) {
point.y += v
} else {
point.y -= v
}
// 创建行驶车辆
moveCarGra = new Graphic({
geometry: new Point({
x: point.x,
y: point.y
}),
symbol: setModelCar(x1, y1, x2, y2)
})
moveLayer.add(moveCarGra)
} else {
const point = moveCarGra.geometry
if (x2 < x1) {
point.x -= (1 / Math.sqrt(1 + p * p)) * v
point.y -= (p / Math.sqrt(1 + p * p)) * v
} else {
point.x += (1 / Math.sqrt(1 + p * p)) * v
point.y += (p / Math.sqrt(1 + p * p)) * v
}
// 创建行驶车辆
moveCarGra = new Graphic({
geometry: new Point({
x: point.x,
y: point.y
}),
symbol: setModelCar(x1, y1, x2, y2)
})
moveLayer.add(moveCarGra)
}
const point = moveCarGra.geometry
if (Math.abs(point.x - x2) <= 1.5 * v && Math.abs(point.y - y2) <= 1.5 * v) {
clearInterval(moving)
startNum = start++
endNum = end++
const point = moveCarGra
point.geometry.x = carPaths[startNum + 1][0]
point.geometry.y = carPaths[startNum + 1][1]
moveLayer.add(point)
if (end < carPaths.length) {
move(start, end)
}
}
}, 200)
}
// 创建车辆
const setModelCar = (x1: any, y1: any, x2: any, y2: any) => {
let modelNewCar = {
type: 'picture-marker',
url: CarImg,
color: '#eb3941',
width: '30px',
height: '30px',
angle: calcAngle(x1, y1, x2, y2) + 90 //朝向
}
return modelNewCar
}
// 初始化车辆
const initModelCar = () => {
let x1 = carPaths[0][0]
let y1 = carPaths[0][1]
let x2 = carPaths[1][0]
let y2 = carPaths[1][1]
// 设置起点
startingPoint = {
type: 'point',
longitude: carPaths[0][0],
latitude: carPaths[0][1]
}
const modelNewCar = {
type: 'picture-marker',
url: CarImg,
color: '#eb3941',
width: '30px',
height: '30px',
angle: calcAngle(x1, y1, x2, y2) + 90 //朝向
}
return modelNewCar
}
// 根据坐标计算角度
const calcAngle = (x1: any, y1: any, x2: any, y2: any) => {
const tan = (Math.atan(Math.abs((y2 - y1) / (x2 - x1))) * 180) / Math.PI + 90
if (x2 > x1 && y2 > y1) {
return -tan + 180
} else if (x2 > x1 && y2 < y1) {
return tan
} else if (x2 < x1 && y2 > y1) {
return tan - 180
} else if (y2 === y1 && x2 > x1) {
return 90
} else if (y2 === y1 && x2 < x1) {
return -90
} else if (y2 > y1 && x2 === x1) {
return 0
} else if (y2 < y1 && x2 === x1) {
return 180
} else {
return -tan
}
}
playPaths - 初始化线路、车辆
start - 开始播放
stopMove - 车辆暂停
goOn - 车辆继续
back - 车辆返回