Cesium开发实践(一)控制小车并视角跟随
程序员文章站
2024-01-01 15:45:34
...
本人是一个前端实习生,最近公司业务需要所有学习了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)是计算转向时相机的位置,这里面星号打不出来。。。
//计算相机位置
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的方法写出来