cesium实体(例如广告牌)移动动画

314 阅读1分钟

实现步骤

  1. 根据websocket或者定时器定时拿到的数据,我们可以得到开始位置和结束位置,
  2. 通过Cesium.Cartesian3.lerpAPI,获取车辆在起点到终点的线段中具体位置,
  3. 通过Cesium.CallbackPropertyAPI,在地图中不断循环画出车辆位置,在视觉上达到移动效果

代码实现

// 因为我的项目要同时判断地图是否存在实体以及实体类型,用于判断是否需要先销毁地图上的实体,所以用entityName1标记一下
let entityName1
export async function drawMoreImgMark(data, idName = 'id', imgName, entityName, coordinateSystemChange) {
  if (!entityName1) {
    entityName1 = entityName
    if (!data.length || !imgName) return
    if (dataSources) {
      viewer.dataSources.remove(dataSources, true)
    }
    dataSources = new Cesium.CustomDataSource(entityName)
    viewer.dataSources.add(dataSources)
  }
  data.forEach(async (item, i) => {
    let latitude, longitude
    if (!item.longitude) return
    if (coordinateSystemChange) {
      // 坐标系转换,与车辆移动动画主题无关
      const arr = transformCoordinate(item.longitude, item.latitude, coordinateSystemChange)
      longitude = arr[0]
      latitude = arr[1]
    }

    const entity = dataSources.entities.getById(item[idName])
    if (entity) {
      //如果实体已经被创建,修改位置
      updateEntityPosition(entity, item)
    } else {
      // 如果是第一次创建实体,直接创建,代码参考我之前的快速画广告牌
    }
  })
}

async function updateEntityPosition(entity, obj) {
  let { longitude, latitude } = obj
  let position = new Cesium.Cartesian3.fromDegrees(longitude, latitude, 100)
  entity.startPosition = entity.endPosition
  entity.endPosition = position
  entity.properties = obj
  let canvasOpt
  canvasOpt = getCanvasOpt(obj)
  let canvas = await drawCanvas(canvasOpt)
  entity.canvas = canvas
  addMoveAnimation(entity, entity.startPosition, position)
}

function addMoveAnimation(Entity, startPosition, endPosition) {
  if (!startPosition || !endPosition) return
  let i = 0,time = 400
  // CallbackProperty有点像动画帧,每隔单位时间调用一次回调,第二个参数是指返回值是否无变化,可能有变化就写false
  Entity.position = new Cesium.CallbackProperty(() => {
    // 设置i的最大值,防止超出
    if (i >= time) {
      i = time
    } else {
      i++
    }
    // 根据初始和结尾点位,使用统计的插值计算动画中每帧实体位置
    // 简单来说就是以两点画一条直线,然后根据i/time得到车在线段中的位置
    return Cesium.Cartesian3.lerp(startPosition, endPosition, i / time, new Cesium.Cartesian3())
  }, false)
  Entity.startPosition = endPosition
}