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 - 车辆返回

posted @ 2023-09-20 16:41  ZerlinM  阅读(240)  评论(0编辑  收藏  举报