cesium实现键盘控制模型姿态变化效果

文章目录

    • 1.实现效果
    • 2.实现方法
      • 2.1实现思路
      • 2.2具体代码

Cesium实战系列文章总目录: 传送门

1.实现效果

2.实现方法

参考官方沙盒示例:传送门

2.1实现思路

(1)加载模型
使用modelfromGltf方法加载模型,API:传送门
cesium实现键盘控制模型姿态变化效果_第1张图片

(2)设置变换矩阵
使用Tranforms类的headingPitchRollToFixedFrame方法设置模型的变化矩阵modelMatrix,API:传送门

姿态和位置变化后的模型转换到WGS84椭球的位置上。
cesium实现键盘控制模型姿态变化效果_第2张图片

(3)监听键盘事件
通过监听键盘事件来更改模型的姿态,键盘事件如下:

键盘 事件
抬头
低头
左转
右转
0 顺时针转
. 逆时针转
+ 加速
- 减速

(4)渲染更新前监听
监听scenepreUpdate事件,API:传送门

当事件发生时,更新模型的姿态和位置。
cesium实现键盘控制模型姿态变化效果_第3张图片

2.2具体代码

具体实现代码如下:

// 初始化viewer
const viewer = new Cesium.Viewer("cesiumContainer", {
    // 允许动画
    shouldAnimate: true,
});


// 设置相机初始位置
viewer.camera.setView({
    destination: {
        x: -2769293.799109788,
        y: 4796599.883886506,
        z: 3171113.878101777
    },
    orientation: {
        heading: 6.283185307179586,
        pitch: -0.7854060155492881,
        roll: 6.283185307179586
    }
})

let headingPitchRoll = new Cesium.HeadingPitchRoll();
// 模型初始位置
let position = new Cesium.Cartesian3.fromDegrees(120, 30, 5000);
// 局部变换坐标系
let fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator("north", "west");

// 每次操作姿态变化为5°
let deltaRadians = Cesium.Math.toRadians(5.0);


// 使用primitive方式加载模型
let airplaneModel = viewer.scene.primitives.add(
    Cesium.Model.fromGltf({
        url: '../.././icons/hz/model/airplane.glb',
        scale: 100.0,
        modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
            position,
            headingPitchRoll,
            Cesium.Ellipsoid.WGS84,
            fixedFrameTransform
        ),
        minimumPixelSize: 256,
    }))


// 添加键盘监听事件
document.addEventListener('keydown', function(e) {
    switch (e.keyCode) {
        // 抬头
        case 38:
            headingPitchRoll.pitch += deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.pitch > Cesium.Math.TWO_PI) {
                headingPitchRoll.pitch -= Cesium.Math.TWO_PI;
            }
            console.log("抬头:pitch+");
            break;

        // 低头
        case 40:
            headingPitchRoll.pitch -= deltaRadians;
            if (headingPitchRoll.pitch < -Cesium.Math.TWO_PI) {
                headingPitchRoll.pitch += Cesium.Math.TWO_PI;
            }
            console.log("低头:pitch-");

            break;
            
        // 左转
        case 37:
            headingPitchRoll.heading -= deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.heading < -Cesium.Math.TWO_PI) {
                headingPitchRoll.heading += Cesium.Math.TWO_PI;
            }
            console.log("左转:heading+");
            break;
            
        // 右转
        case 39:
            headingPitchRoll.heading += deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.heading > Cesium.Math.TWO_PI) {
                headingPitchRoll.heading -= Cesium.Math.TWO_PI;
            }
            console.log("右转:heading-");
            break;
            
        // 顺时针
        case 96:
            headingPitchRoll.roll += deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.roll > Cesium.Math.TWO_PI) {
                headingPitchRoll.roll -= Cesium.Math.TWO_PI;
            }
            console.log("顺时针翻滚:roll+");
            break;
            
        // 逆时针
        case 110:
            headingPitchRoll.roll -= deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.roll < -Cesium.Math.TWO_PI) {
                headingPitchRoll.roll += Cesium.Math.TWO_PI;
            }
            console.log("逆时针翻滚:roll-");
            break;
            
        // 加速
        case 107:
            speed += 10
            speed = Math.min(speed, 10000);
            console.log("加速:" + speed);
            break;
        // 减速
        case 109:
            speed -= 10;
            speed = Math.max(speed, 100);
            console.log("减速:" + speed);
            break;

        default:
            break;
    }
})

// 速度
let speed = 100;
// 速度向量
let speedVector = new Cesium.Cartesian3();

// 飞行路径
const pathPosition = new Cesium.SampledPositionProperty();
const entityPath = viewer.entities.add({
    position: pathPosition,
    name: "飞行路径",
    path: {
        show: true,
        leadTime: 0,
        trailTime: 60,
        width: 20,
        resolution: 1,
        material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.3,
            taperPower: 0.3,
            color: Cesium.Color.PALEGOLDENROD,
        }),
    },
});

// 渲染更新前阶段添加监听
viewer.scene.preUpdate.addEventListener(() => {
    speedVector = Cesium.Cartesian3.multiplyByScalar(
        Cesium.Cartesian3.UNIT_X,
        speed / 10,
        speedVector
    );
    position = Cesium.Matrix4.multiplyByPoint(
        airplaneModel.modelMatrix,
        speedVector,
        position
    );
    // 将点添加到路径中
    pathPosition.addSample(Cesium.JulianDate.now(), position);

	  // 更新模型姿态与位置
    Cesium.Transforms.headingPitchRollToFixedFrame(
        position,
        headingPitchRoll,
        Cesium.Ellipsoid.WGS84,
        fixedFrameTransform,
        airplaneModel.modelMatrix
    )
})

你可能感兴趣的:(cesium,gis,ceisum)