欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Cesium开发实践(一)控制小车并视角跟随

程序员文章站 2024-01-01 15:45:34
...

本人是一个前端实习生,最近公司业务需要所有学习了cesium,想记录一下。如果觉得还可以就点个赞,或者有啥要改进的也可以提出来交流一下。

效果图

Cesium开发实践(一)控制小车并视角跟随
实现思路

1、添加模型
2、监听键盘按键
3、计算坐标
4、设置相机位置和角度
5、移动小车

初始化

因为我是用的vue结合的sesium开发,里面一下其他功能就不在这里细说,是通过点击屏幕,确定小车坐标来生成的小车。

		let newStr =[parseFloat(str[0].substring(2)),parseFloat(str[1].substring(2)),parseFloat(str[2].substring(2))]
        // 小车旋转角度
        let radian = Cesium.Math.toRadians(2.0);
        // 小车的速度
        let speed = 0.2;
        // 速度矢量
        let speedVector = new Cesium.Cartesian3();
        let scene = viewer.scene;
        // 起始位置
        let position = Cesium.Cartesian3.fromDegrees(newStr[0],newStr[1],newStr[2])
        // 用于设置小车方向
        let hpRoll = new Cesium.HeadingPitchRoll();
        let fixedFrameTransforms =  Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west');

创建模型

let carPrimitive = scene.primitives.add(Cesium.Model.fromGltf({
                id:'mycar',
                url:'/static/model/GLTFformat/taxi.glb',
                modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84,fixedFrameTransforms),
            }))

监听键盘

// 小车状态标志
        let flag = {
            moveUp:false,
            moveDown:false,
            moveLeft:false,
            moveRight:false
        };
        // 根据键盘按键返回标志
        function setFlagStatus(key,value) {
            switch (key.keyCode){
                case 37:
                    // 左
                    flag.moveLeft = value;
                    break;
                case 38:
                    // 上
                    flag.moveUp = value;
                    break;
                case 39:
                    // 右
                    flag.moveRight = value;
                    break;
                case 40:
                    flag.moveDown = value;
                    // 下
                    break;
            }
        }
        document.addEventListener('keydown',(e)=>{
            setFlagStatus(e, true);
        });
 
        document.addEventListener('keyup',(e)=>{
            setFlagStatus(e, false);
        });
        // moveCar(true);
        var count = 0;
        viewer.clock.onTick.addEventListener((clock)=>{
          
            if(flag.moveUp){
                if(flag.moveLeft){
                    hpRoll.heading -= radian;
                    count += 2;
                }
                if(flag.moveRight){
                    hpRoll.heading += radian;
                    count -= 2;
                }
                moveCar(1);
            }else if(flag.moveDown){
                if(flag.moveLeft){
                    hpRoll.heading -= radian;
                    count += 2;
                }
                if(flag.moveRight){
                    hpRoll.heading += radian;
                    count -= 2;
                }
                moveCar(-1);
            }else {
              if(flag.moveLeft){
                    hpRoll.heading -= radian;
                    count += 2;
                    moveCar(0)
                }
                if(flag.moveRight){
                    hpRoll.heading += radian;
                    count -= 2;
                    moveCar(0)
                }
            }
        });

移动小车

function moveCar(isUP) {
            // 计算速度矩阵
            if(isUP===1){
                speedVector = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_X,speed,speedVector);
            }else if(isUP===-1){
                speedVector = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_X,-speed,speedVector);
            }else{
              speedVector = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_X,0,speedVector);
            }
            
            // 根据速度计算出下一个位置的坐标
            position = Cesium.Matrix4.multiplyByPoint(carPrimitive.modelMatrix ,speedVector, position);
           
            // 小车移动
            Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransforms, carPrimitive.modelMatrix);
        }
      this.hideCar=3

相机位置

下面的这个0.00001852398509是我根据计算得出的一个经纬度差值,符合我用这个小车模型的需要。
Math.sin((270+count)2Math.PI/360)和Math.cos((270+count)2Math.PI/360)是计算转向时相机的位置,这里面星号打不出来。。。Cesium开发实践(一)控制小车并视角跟随

			//计算相机位置
            var cartesian3=new Cesium.Cartesian3(position.x,position.y,position.z);
            var cartographic=scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
            var lng=Cesium.Math.toDegrees(cartographic.longitude) +0.00001852398509*5*Math.cos((270+count)*2*Math.PI/360); 
            var lat=Cesium.Math.toDegrees(cartographic.latitude) +0.00001852398509*5*Math.sin((270+count)*2*Math.PI/360);           
            var alt=cartographic.height +5 ;
            // 获取指定经纬度的高程
            //这部分是想要获取高程来实现贴地,目前这一块还没完善,有需求的可以借鉴一下
            //var toH=new Cesium.Cartographic.fromDegrees(lng,lat)
            //var h2 = viewer.scene.sampleHeight(toH)

            viewer.camera.setView({
                destination:Cesium.Cartesian3.fromDegrees(lng,lat,alt),
                orientation:{
                  // 指向  镜头随小车变化角度
                  heading:hpRoll.heading,
                  // 视角固定
                  pitch:Cesium.Math.toRadians(-15.0),
                  roll:0.0
                }
              });

这篇文章就先介绍这么多,另外有使用viewer.entities.add方法添加的模型也能实现这些功能,并且entities能使用viewer.trackedEntity。这种追踪实体的方法可能也是会有具体需求的,下一篇把使用entitis的方法写出来

上一篇:

下一篇: