Cesium键盘控制模型自由运动

文章介绍了如何使用Cesium库实现第一人称视角的模型漫游,通过键盘控制模型的抬头、低头、转向以及速度调整,并支持切换至上帝视角和自定义视角。
摘要由CSDN通过智能技术生成

 第一视角漫游封装类文件,使用键盘控制第一视角漫游,模型姿态:↑:抬头;↓:低头;←:左转;→:右转;9:顺时针旋转;0:逆时针旋转;1:加速;2:减速;Ctrl:切换视角。

import * as Cesium from "cesium";
import myPrimitive from "../primitiveJS/primitive";
let headingPitchRoll = new Cesium.HeadingPitchRoll();
// 局部变换坐标系
let fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator(
  "north",
  "west"
);
// 每次姿态变化4°
let deltaRadians = Cesium.Math.toRadians(4);
// 速度向量
let Vector = new Cesium.Cartesian3();
// 控制视角
let view = "none";
// 地图容器
let V = "";
// 计数器,只添加一次模型
let firstModel = "";
let position;
// 模型运动速度
let speed;
// 自定义控制模型视角Cesium.Cartesian3
let xyz = [];
// 自定义控制模型视角Cesium.Cartesian3
let firstRoamXYZ = [0, -100, 10];
// 自定义控制模型视角Cesium.Cartesian3
let godRoamXYZ = [0, 0, 100];
// 模型参数对象
let myParameter = {};
/**
 * 第一视角漫游
 */
class firstRoam {
  /**
   * 构造函数
   * @param {*} viewer -地图主窗口
   */
  constructor(viewer) {
    V = viewer;
  }
  /**
   * 第一视角漫游加载方法
   * @param: 使用键盘控制第一视角漫游,模型姿态:↑:抬头;↓:低头;←:左转;→:右转;9:顺时针旋转;0:逆时针旋转;1:加速;2:减速;Ctrl:切换视角
   * @param {Object} parameter -第一视角漫游默认配置项
   * @param {String} parameter.modelPath -模型路径
   * @param {Array} parameter.startPosition -模型初始坐标位置
   * @param {Number} [parameter.minSize] -模型的最小显示像素大小,默认64
   * @param {Number} [parameter.maxSize] -模型的最大显示像素大小,默认128
   * @param {Number} [parameter.speed] -漫游速度,默认为1
   * @return {Cesium.Primitive} -返回飞行对象实体
   */
  start(parameter) {
    if (!firstModel) {
      position = new Cesium.Cartesian3.fromDegrees(...parameter.startPosition);
      V.camera.flyTo({
        // fromDegrees()方法,将经纬度和高程转换为笛卡尔坐标系
        destination: Cesium.Cartesian3.fromDegrees(...parameter.startPosition), //设置位置
        orientation: {
          heading: Cesium.Math.toRadians(0),
          pitch: Cesium.Math.toRadians(-10),
          roll: 0.0,
        },
      });
      myParameter.clickPointH = parameter.startPosition;
      myParameter.modelPath = parameter.modelPath;
      myParameter.maxSize = parameter.maxSize;
      myParameter.minSize = parameter.minSize;
      myParameter.rotation = 90;
      speed = parameter.speed || 1;
      // 模型初始位置,这是我自己封装的方法,大家可以自己使用primitive创建对象,简单的呢
      this.priCover = new myPrimitive(V);
      // 使用primitive方式加载模型
      firstModel = this.priCover.PrimitiveModel(myParameter);
      // 模型行进-俯仰-滚动角度的转换
      firstModel.modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
        position,
        headingPitchRoll,
        Cesium.Ellipsoid.WGS84,
        fixedFrameTransform
      );
    }
    if (this.firstDown) {
      document.removeEventListener("keydown", this.firstDown, false);
    }
    if (this.preUpdate) {
      // 移除模型移动事件
      V.scene.preUpdate.removeEventListener(this.preUpdate);
    }
    // 添加键盘监听事件
    document.addEventListener(
      "keydown",
      (this.firstDown = function (e) {
        switch (e.key) {
          // 抬头
          case "ArrowUp":
            headingPitchRoll.pitch += deltaRadians;
            break;

          // 低头
          case "ArrowDown":
            headingPitchRoll.pitch -= deltaRadians;
            break;

          // 左转
          case "ArrowLeft":
            headingPitchRoll.heading -= deltaRadians;
            break;

          // 右转
          case "ArrowRight":
            headingPitchRoll.heading += deltaRadians;
            break;

          // 顺时针
          case "9":
            headingPitchRoll.roll += deltaRadians;
            break;

          // 逆时针
          case "0":
            headingPitchRoll.roll -= deltaRadians;
            break;

          // 加速
          case "1":
            speed += 10;
            speed = Math.min(speed, 10000);
            break;
          // 减速
          case "2":
            speed -= 10;
            speed = Math.max(speed, 10);
            break;
          default:
            break;
        }
      })
    );
    // 渲染更新前阶段添加监听
    V.scene.preUpdate.addEventListener(
      (this.preUpdate = () => {
        // 乘以速度向量,计算速度矩阵
        Vector = Cesium.Cartesian3.multiplyByScalar(
          Cesium.Cartesian3.UNIT_X,
          speed / 10,
          Vector
        );
        // 根据速度计算下一个位置,本地坐标转世界坐标
        position = Cesium.Matrix4.multiplyByPoint(
          firstModel.modelMatrix,
          Vector,
          position
        );
        // 更新模型姿态与位置
        Cesium.Transforms.headingPitchRollToFixedFrame(
          position,
          headingPitchRoll,
          Cesium.Ellipsoid.WGS84,
          fixedFrameTransform,
          firstModel.modelMatrix
        );
        if (view != "none") {
          V.camera.lookAt(position, new Cesium.Cartesian3(...xyz));
        }
      })
    );
    return firstModel;
  }
  /**
   * 漫游视角切换方法
   * @param {String} value -value为'first'为第一视角,'god'为上帝视角,'definition'为自定义视角,'none'为取消视角跟随
   * @param {Array} newModelXYZ -自定义视角时可用,通过[x(相机在模型左右),y(相机在模型前后),z(相机在模型上下)]设置视角相机位置
   */
  changeView(value, newModelXYZ) {
    view = value;
    if (value == "first") {
      // 更新相机位置(第一视角)
      xyz = firstRoamXYZ;
    } else if (value == "god") {
      // 更新相机位置(上帝视角)
      xyz = godRoamXYZ;
    } else if (value == "definition") {
      xyz = newModelXYZ;
    }
  }
  /**
   * 暂停第一视角漫游事件
   */
  stop() {
    // 移除第一视角键盘事件
    document.removeEventListener("keydown", this.firstDown, false);
    // 移除模型移动事件
    V.scene.preUpdate.removeEventListener(this.preUpdate);
    V.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
  }
  /**
   * 销毁第一视角漫游事件
   */
  quit() {
    this.stop();
    V.scene.primitives.remove(firstModel);
    firstModel = "";
    view == "none";
  }
}
export default firstRoam;

 以下为详细步骤,但不是具体代码,不可直接粘贴使用哦

// 1.导入第一视角漫游文件
import firstRoam from "../firstRoam.js";
// 2.初始化地图对象
const viewer = new Cesium.Viewer("cesiumContainer", {
  animation: false, //左下角的动画仪表盘
  baseLayerPicker: false, //右上角的图层选择按钮
  geocoder: true, //搜索框
  homeButton: true, //home按钮
  sceneModePicker: false, //模式切换按钮
  timeline: false, //底部的时间轴
  navigationHelpButton: false, //右上角的帮助按钮,
  fullscreenButton: false, //右下角的全屏按钮
  infoBox: false, //小弹窗
  selectionIndicator: false,
  zoomIndicatorContainer: false,
  // shadows: true,//阴影
  shouldAnimate: true, //允许动画
});
// 3.初始化第一视角漫游方法
this.first = new firstRoam(viewer);
// 4.定义漫游参数对象
let aircrafRoamParam = {
  modelPath: "SampleData/models/CesiumAir/Cesium_Air.glb",
  startPosition,
  // 模型显示的最大像素值
  maxSize: 130,
  // 模型显示的最小像素值
  minSize: 50,
  // 漫游速度
  speed: 10,
};
// 5.执行开始飞行方法,返回飞行对象实体
this.aircraf = this.first.start(aircrafRoamParam);
// 6.执行停止飞行方法
this.first.stop();
// 7.执行飞行销毁方法
this.first.quit();
// 8.更改飞行视角方法,value为'first'为第一视角,'god'为上帝视角,'definition'为自定义视角,'none'为取消视角跟随
this.first.changeView(value, newModelXYZ);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要随地大便

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值