cesium 请问如何通过点击车辆模型,实现视角跟随?

let socketInfo = 'xxxxxx'
let ws = new WebSocket(socketInfo)
let pingInterval = ref(null) // 心跳间隔ID
let viewer = null
let entity = null
let polylineInitialized = false; // 轨迹线是否已初始化的标志
let polylineEntity = null; // 用于存储轨迹线实体
let pointEntity = null;
const positionParams = []; // 用于存储所有的位置参数数据
const bufferLimit = 50; // 缓冲区大小限制
// 加载websocket
function webValue() {
  // 初始Websocket
  const onOpen = () => {
    const data = JSON.stringify({ command: 1, serializeAlgorithm: 1, token: window.localStorage.getItem('token') });
    ws.send(data); // 发送JSON字符串
    // 设置心跳间隔为5秒
    pingInterval.value = window.setInterval(() => {
      const pingMessage = JSON.stringify({
        command: 2,
        serializeAlgorithm: 1
      });
      ws.send(pingMessage);
    }, 5000);
  };
  // 接收websocket数据
  const onMessage = async (event) => {
    const data = JSON.parse(event.data);
    if (data.data == undefined) {
      console.log('未响应');
    } else {
      processPositionParams(data.data);
      updateCarModelPosition(positionParams);// 实时更新车辆移动位置
      if (!polylineInitialized) {
        initializePolyline(positionParams); // 初始化轨迹线
        polylineInitialized = true; // 标记轨迹线已初始化
      } else {
        updatePolylinePosition(positionParams); // 更新轨迹线位置
      }
    }
  };
  // 封装处理返回的参数
  function processPositionParams(data) {
    const targetingTypes = {
      0x10: 'RTK',
      0x11: 'UWB',
      0x12: '融合'
    };
    const newPositionParam = {
      TargetingType: targetingTypes[data.type],
      UID: data.uid,
      Angle: data.angle,
      Height: data.height,
      longitude: data.longitude,
      latitude: data.latitude
    };
    positionParams.push(newPositionParam);
    // 超过缓冲区大小限制时移除最旧的位置参数数据
    if (positionParams.length > bufferLimit) {
      positionParams.shift();
    }
    const labelText = `终端ID:${data.uid},定位类型:${targetingTypes[data.type]}\n经度:${data.longitude},纬度:${data.latitude}\n角度:${data.angle},高度:${data.height}`;
    point(positionParams, labelText);// 更新实体点位置信息
  }
  const onClose = () => {
    window.clearInterval(pingInterval.value); // 清除心跳间隔定时器
    console.log('Websocket连接关闭');
    webValue();
  };
  const onError = (error) => {
    console.log('Websocket连接错误');
    ws.close();
    window.clearInterval(pingInterval.value); // 清除心跳间隔定时器
    webValue();
  };
  ws.addEventListener('open', onOpen);
  ws.addEventListener('message', onMessage);
  ws.addEventListener('close', onClose);
  ws.addEventListener('error', onError);
}
-------------------------------------
// 绘制车辆模型和轨迹点、轨迹线
let checkedPoint = ref(true);
let checkedLines = ref(false);
// 保存checkedPoint和checkedLines的值到LocalStorage
function saveCheckedValues() {
  localStorage.setItem('checkedPoint', JSON.stringify(checkedPoint.value));
  localStorage.setItem('checkedLines', JSON.stringify(checkedLines.value));
}
// 从LocalStorage中获取checkedPoint和checkedLines的值
function loadCheckedValues() {
  const storedCheckedPoint = localStorage.getItem('checkedPoint');
  const storedCheckedLines = localStorage.getItem('checkedLines');
  if (storedCheckedPoint) {
    checkedPoint.value = JSON.parse(storedCheckedPoint);
  }
  if (storedCheckedLines) {
    checkedLines.value = JSON.parse(storedCheckedLines);
  }
}
// 监听checkedPoint和checkedLines的变化,并保存到LocalStorage
watch([checkedPoint, checkedLines], saveCheckedValues, { deep: true });
// 在页面加载时加载checkedPoint和checkedLines的值
window.addEventListener('load', loadCheckedValues);
// 车辆模型
let carModelData = null;
let shouldFollowCar = false; // 标志位
function updateCarModelPosition(positions) {
  if (positions.length === 0) {
    return;
  }
  const latestPosition = positions[positions.length - 1];
  const cartesian3 = Cesium.Cartesian3.fromDegrees(latestPosition.longitude, latestPosition.latitude, 0.4);
  if (!carModelData) {
    createCarModel(cartesian3, latestPosition.Angle);
  } else {
    carModelData.position = cartesian3;
    const headingPitchRoll = new Cesium.HeadingPitchRoll(
      Cesium.Math.toRadians(latestPosition.Angle + 90),
      Cesium.Math.toRadians(0),
      Cesium.Math.toRadians(0)
    );
    carModelData.orientation = Cesium.Transforms.headingPitchRollQuaternion(cartesian3, headingPitchRoll);
  }
}

function createCarModel(cartesian3, angle) {
  const headingPitchRoll = new Cesium.HeadingPitchRoll(
    Cesium.Math.toRadians(angle + 90),
    Cesium.Math.toRadians(0),
    Cesium.Math.toRadians(0)
  );
  const scaleByDistance = new Cesium.NearFarScalar(200, 120, 1200, 0.6);
  const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000);
  carModelData = viewer.entities.add({
    position: cartesian3,
    orientation: Cesium.Transforms.headingPitchRollQuaternion(cartesian3, headingPitchRoll),
    model: {
      uri: "http://127.0.0.1:5501/car/scene.gltf",
      scale: 75,
      scaleByDistance,
      distanceDisplayCondition,
    },
    id: 'carModel' // 添加id属性
  });

}
---------------------------------------------------------------
// 轨迹点  和  轨迹线   和  标签文字
let positionsArray = [];
let entityList = [];
function point(positions, labelText) {
  const cartesian3Array = [];
  positionsArray = positions.flatMap(pos => [pos.longitude, pos.latitude]);
  // 移除之前的实体点
  for (const entity of entityList) {
    viewer.entities.remove(entity);
  }
  entityList = [];
  for (const position of positions) {
    let entityIndex = entityList.length;
    const cartesian3 = Cesium.Cartesian3.fromDegrees(
      position.longitude,
      position.latitude,
      0.02
    );
    const pointLabel = new Cesium.Entity({
      position: cartesian3,
      point: {
        pixelSize: 10,
        color: Cesium.Color.BLUE,
        show: checkedPoint.value,
        outlineColor: Cesium.Color.WHITE,
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 500),
        scaleByDistance: new Cesium.NearFarScalar(100, 1, 300, 0.5),
        outlineWidth: 1,
      },
      // label: {
      //   text: labelText,
      //   font: '14pt monospace',
      //   show: new Cesium.CallbackProperty(() => {
      //     return entityIndex === entityList.length - 1;
      //   }, false),
      //   style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      //   outlineWidth: 2,
      //   verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      //   pixelOffset: new Cesium.Cartesian2(0, -9),
      //   scaleByDistance: new Cesium.NearFarScalar(300, 1, 1000, 0.4), //设置随图缩放距离和比例
      //   scale: 1,
      //   fillColor: Cesium.Color.WHITE,//标签的文本填充颜色。
      //   outlineColor: Cesium.Color.WHITE,//标签的文本轮廓颜色。
      // },
    });
    entityList.push(pointLabel);
    viewer.entities.add(pointLabel);
    cartesian3Array.push(cartesian3);
  }
}
--------------------------------------------------------
// 创建新的轨迹线
let polylineGeometry = null;
let geometryInstance = null;
function initializePolyline(positions) {
  const positionsArray = positions.flatMap(pos => [pos.longitude, pos.latitude]);
  const positionsInCartesian = Cesium.Cartesian3.fromDegreesArray(positionsArray);
  polylineGeometry = new Cesium.PolylineGeometry({
    positions: positionsInCartesian,
    width: 5,
    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 500),
    scaleByDistance: new Cesium.NearFarScalar(100, 10, 500, 1),
  });
  geometryInstance = new Cesium.GeometryInstance({
    geometry: polylineGeometry,
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
    }
  });
  const primitive = new Cesium.Primitive({
    geometryInstances: geometryInstance,
    appearance: new Cesium.PolylineMaterialAppearance({
      material: Cesium.Material.fromType(Cesium.Material.ColorType)
    })
  });
  viewer.scene.primitives.add(primitive);
}
// 更新轨迹线位置
function updatePolylinePosition(positions) {
  if (geometryInstance) {
    const positionsArray = positions.flatMap(pos => [pos.longitude, pos.latitude]);
    const positionsInCartesian = Cesium.Cartesian3.fromDegreesArray(positionsArray);
    polylineGeometry.positions = positionsInCartesian;
    geometryInstance.geometry = polylineGeometry;
    geometryInstance.show = checkedLines.value;
  }
}

阅读 3.2k
1 个回答
viewer.screenSpaceEventHandler.setInputAction(function (click) {
  var pickedObject = viewer.scene.pick(click.position);
  if (Cesium.defined(pickedObject) && pickedObject.id === carModelData) {
    shouldFollowCar = !shouldFollowCar; // 切换跟随状态
  }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

function updateCameraPosition() {
  if (shouldFollowCar && carModelData) {
    var position = carModelData.position.getValue(Cesium.JulianDate.now());
    if (position) {
      viewer.camera.flyTo({
        destination: position,
        orientation: {
          heading: viewer.camera.heading,
          pitch: viewer.camera.pitch,
          roll: viewer.camera.roll
        }
      });
    }
  }
}

viewer.clock.onTick.addEventListener(updateCameraPosition);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题