第一视角漫游封装类文件,使用键盘控制第一视角漫游,模型姿态:↑:抬头;↓:低头;←:左转;→:右转;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);