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


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

1.实现效果

在这里插入图片描述

2.实现方法

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

2.1实现思路

(1)加载模型
使用modelfromGltf方法加载模型,API:传送门
在这里插入图片描述

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

姿态和位置变化后的模型转换到WGS84椭球的位置上。
在这里插入图片描述

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

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

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

当事件发生时,更新模型的姿态和位置。
在这里插入图片描述

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键盘控制器,您需要监听键盘事件并根据按下的键更新相机的位置和朝向。以下是一个示例代码,它演示了如何使用键盘控制相机的移动和旋转。 ``` var scene = viewer.scene; var canvas = viewer.canvas; var camera = scene.camera; // 定义键盘控制器参数 var controller = { speed: 100.0, // 移动速度 rotateSpeed: 2.0, // 旋转速度 keys: { W: 87, // 向前移动 S: 83, // 向后移动 A: 65, // 向左移动 D: 68, // 向右移动 Q: 81, // 向上移动 E: 69, // 向下移动 LEFT: 37, // 左旋转 UP: 38, // 上旋转 RIGHT: 39, // 右旋转 DOWN: 40 // 下旋转 } }; // 监听键盘事件 var handler = new Cesium.ScreenSpaceEventHandler(canvas); handler.setInputAction(function (event) { var key = event.keyCode; if (key === controller.keys.W) { camera.moveForward(controller.speed); } else if (key === controller.keys.S) { camera.moveBackward(controller.speed); } else if (key === controller.keys.A) { camera.moveLeft(controller.speed); } else if (key === controller.keys.D) { camera.moveRight(controller.speed); } else if (key === controller.keys.Q) { camera.moveUp(controller.speed); } else if (key === controller.keys.E) { camera.moveDown(controller.speed); } else if (key === controller.keys.LEFT) { camera.rotateLeft(Cesium.Math.toRadians(controller.rotateSpeed)); } else if (key === controller.keys.UP) { camera.rotateUp(Cesium.Math.toRadians(controller.rotateSpeed)); } else if (key === controller.keys.RIGHT) { camera.rotateRight(Cesium.Math.toRadians(controller.rotateSpeed)); } else if (key === controller.keys.DOWN) { camera.rotateDown(Cesium.Math.toRadians(controller.rotateSpeed)); } }, Cesium.ScreenSpaceEventType.KEY_DOWN); ``` 在上面的示例代码中,我们定义了一个名为`controller`的对象,其中包含了键盘控制器的参数,例如移动速度、旋转速度和键位映射表。然后,我们使用`ScreenSpaceEventHandler`类监听Canvas上的键盘事件,并根据按下的键来更新相机的位置和朝向。例如,当按下`W`键时,我们调用`camera.moveForward()`方法向前移动相机。 当然,这只是一个简单的示例。您可以根据自己的需要定制键盘控制器的逻辑,例如添加缩放、倾斜等功能。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

右弦GISer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值