javascript
复制代码
class CameraNavigation {
constructor(viewer) {
this.viewer = viewer;
this.flyDuration = 0.5
this.clickEvent = true;
this.moveEndHandler = null;
this.speed = null
this.moveSpeed = null;
this.height = null;
this.buttonEvent = {};
this.rotationSpeed = 10;
this.customZoomStep = 200;
this.deviceType = this.getDeviceType();
this.initControl()
this.btnSAddEventListenerName = []
}
getDeviceType() {
const userAgent = navigator.userAgent;
console.log(userAgent);
if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
return "平板";
} else if (
/(mobi|opera mini|iphone|ipod|android|blackberry|windows phone)/i.test(
userAgent
)
) {
return "手机";
} else {
return "电脑";
}
}
initControl() {
this.downStart = 'touchstart';
this.upEnd = 'touchend';
if (this.deviceType == "电脑") {
this.downStart = "mousedown"
this.upEnd = "mouseup"
}
console.log(this.upEnd, this.downStart);
}
setCameraPitch(pitch = 5){
const camera = this.viewer.camera;
// 获取当前相机的方向(heading 和 pitch)
const currentHeading = camera.heading;
const currentPitch = camera.pitch;
console.log(currentPitch, 'currentPitch');
// 将相机的方向设置为新的 roll,保持 heading 和 pitch 不变
camera.setView({
orientation: {
heading: currentHeading,
pitch: currentPitch + Cesium.Math.toRadians(pitch),
roll: camera.roll,
},
});
}
zoomMap(direction) {
const camera = this.viewer.camera;
const position = camera.positionWC.clone();
const directionVector = camera.directionWC.clone();
const height = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height;
// 根据相机高度调整缩放的比例
// const scale = Math.ceil(height / 1000.0);
// console.log(scale,'scale');
// let dire = scale>1?scale*direction * 100:direction * 100
// console.log(dire,'dire');
const scale = Math.ceil(height / 1.0);
let dire = scale * direction
// 方向矢量与缩放量的乘积
const zoomVector = Cesium.Cartesian3.multiplyByScalar(directionVector, dire, new Cesium.Cartesian3());
// 新位置为当前位置加上缩放后的矢量
const newPosition = Cesium.Cartesian3.add(position, zoomVector, new Cesium.Cartesian3());
const heading = camera.heading;
const pitch = camera.pitch;
camera.flyTo({
destination: newPosition,
orientation: {
heading: heading,
pitch: pitch,
},
duration: 0.5, // 调整飞行动画的持续时间
});
}
// 缩小地图
zoomOut() {
try {
var currentDistance = this.viewer.camera.positionCartographic.height;
var currentLongitude = this.viewer.camera.positionCartographic.longitude;
var currentLatitude = this.viewer.camera.positionCartographic.latitude;
var newDistance = currentDistance + this.customZoomStep;
var newLongitude = currentLongitude;
var newLatitude = currentLatitude;
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromRadians(newLongitude, newLatitude, newDistance),
orientation: {
heading: this.viewer.camera.heading, // 保持航向角不变
pitch: this.viewer.camera.pitch,
roll: this.viewer.camera.roll
},
duration:0.5
})
} catch (error) {
console.log(error, 'error');
}
}
setCameraHeight(insertStep) {
try {
var currentDistance = this.viewer.camera.positionCartographic.height;
var currentLongitude = this.viewer.camera.positionCartographic.longitude;
var currentLatitude = this.viewer.camera.positionCartographic.latitude;
var newDistance = currentDistance + insertStep;
var newLongitude = currentLongitude;
var newLatitude = currentLatitude;
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromRadians(newLongitude, newLatitude, newDistance),
orientation: {
heading: this.viewer.camera.heading, // 保持航向角不变
pitch: this.viewer.camera.pitch,
roll: this.viewer.camera.roll
},
duration:0.5
})
} catch (error) {
console.log(error, 'error');
}
}
// 放大地图
zoomIn() {
try {
var currentDistance = this.viewer.camera.positionCartographic.height;
var currentLongitude = this.viewer.camera.positionCartographic.longitude;
var currentLatitude = this.viewer.camera.positionCartographic.latitude;
var newDistance = currentDistance - this.customZoomStep;
var newLongitude = currentLongitude;
var newLatitude = currentLatitude;
if (currentDistance > 0) {
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromRadians(newLongitude, newLatitude, newDistance),
orientation: {
heading: this.viewer.camera.heading, // 保持航向角不变
pitch: this.viewer.camera.pitch,
roll: this.viewer.camera.roll
},
duration:0.5
})
}
} catch (error) {
console.log(error, 'error');
}
}
setupEventListeners() {
if (this.moveSpeed) {
this.speed = this.moveSpeed
}
let currentHeightInit = this.viewer.camera.positionCartographic.height;
this.height = Math.round(currentHeightInit);
// 添加高度变化监听事件
this.moveEndHandler = () => {
console.log(111);
const currentHeight = this.viewer.camera.positionCartographic.height;
this.height = Math.round(currentHeight);
if (!this.moveSpeed) {
this.speed = this.height / 100
} else {
this.speed = this.moveSpeed
}
}
this.viewer.camera.moveEnd.addEventListener(this.moveEndHandler);
console.log(this.height, 'this.height');
}
setupCameraNavigation() {
// 定义事件处理函数
function handleKeyDown(event) {
console.log(event.key);
switch (event.key) {
// case 'ArrowUp' || 'w':
case 'w':
this.moveCamera("Up");
break;
// case 'ArrowDown' || 'd':
case 's':
this.moveCamera("Down");
break;
// case 'ArrowLeft' || 's':
case 'a':
this.moveCamera("Left");
break;
// case 'ArrowRight' || 'a':
case 'd':
this.moveCamera("Right");
break;
case 'q':
this.rotationCamera(10);
break;
case 'e':
this.rotationCamera(-10);
break;
default:
break;
}
}
// 添加键盘按下事件监听器
document.addEventListener('keydown', handleKeyDown.bind(this));
}
removeCameraNavigation() {
try {
this.btnSAddEventListenerName.forEach(ele => {
if (this.clickEvent) {
document.querySelector(ele.id).removeEventListener('click', this.buttonEvent[ele.eventName].up, false)
} else {
document.querySelector(ele.id).removeEventListener(this.downStart, this.buttonEvent[ele.eventName].up, false)
document.querySelector(ele.id).removeEventListener(this.upEnd, this.buttonEvent[ele.eventName].upEnd, false)
}
})
// 移除键盘按下事件监听器
// document.removeEventListener('keydown', this.handleKeyDown);
// 取消高度变化监听事件
this.viewer.camera.moveEnd.removeEventListener(this.moveEndHandler);
this.btnSAddEventListenerName = []
this.buttonEvent = {}
} catch (error) {
console.log(error, 'error');
}
}
moveCamera(type = 'Up') {
try {
// 获取当前Cesium相机
const camera = this.viewer.camera;
// 获取当前相机的位置和方向
const currentPosition = camera.positionCartographic.clone();
const currentHeading = camera.heading;
// 定义移动的距离和方向
const distance = this.speed; // 1000米示例距离
let bearing = Cesium.Math.toDegrees(currentHeading); // 使用当前方向
switch (type) {
case 'Up': // 向上移动
bearing = Cesium.Math.toDegrees(currentHeading)
break;
case 'Down': // 向下移动
bearing = Cesium.Math.toDegrees(currentHeading - Math.PI); // 使用当前方向
break;
case 'Left': // 向左移动
bearing = Cesium.Math.toDegrees(currentHeading - Math.PI / 2); // 使用当前方向
break;
case 'Right': // 向右移动
bearing = Cesium.Math.toDegrees(currentHeading + Math.PI / 2); // 使用当前方向
break;
default:
break;
}
// 使用Turf.js计算新位置
const destination = turf.destination(
turf.point([Cesium.Math.toDegrees(currentPosition.longitude), Cesium.Math.toDegrees(currentPosition.latitude)]),
distance,
bearing,
{ units: 'meters' }
);
// 将新位置转换为Cesium坐标
const newCartesian = Cesium.Cartesian3.fromDegrees(destination.geometry.coordinates[0], destination.geometry.coordinates[1], this.height);
// 设置相机位置
// camera.position = newCartesian;
camera.flyTo({
destination: newCartesian,
orientation: {
heading: camera.heading,
pitch: camera.pitch,
roll: camera.roll
},
duration: this.flyDuration
})
} catch (error) {
console.log(error, 'error');
}
}
// rotationCamera(n) {
// // 获取当前相机
// const camera = this.viewer.camera;
// // 获取当前相机的方向(heading)
// const currentHeading = camera.heading;
// // 设置旋转后的方向(顺时针旋转10度)
// const newHeading = currentHeading + Cesium.Math.toRadians(n);
// // 将相机旋转到新的方向
// camera.setView({
// orientation: {
// heading: newHeading,
// pitch: camera.pitch,
// roll: camera.roll,
// },
// });
// }
rotationCamera(n) {
let centerScreen = this.getScreenCenterCoordinates();
console.log(centerScreen, 'getScreenCenterCoordinates');
// 获取当前相机
const camera = this.viewer.camera;
// console.log(camera.position, 'camera');
let p = this.Cartesian3_to_WGS84(camera.position)
// console.log(p, 'ppp');
// 获取当前相机的方向(heading)
var point1 = turf.point(centerScreen);
var point2 = turf.point(p);
var options = { units: 'meters' };
var bearing = turf.bearing(point1, point2);
var bearing1 = turf.bearing(point2, point1);
console.log(bearing, bearing1, 'bearing1bearing1');
var distance = turf.distance(point1, point2, options);
// console.log(Cesium.Math.toRadians(n), 'Cesium.Math.toRadians(n)Cesium.Math.toRadians(n)');
let newBearing = bearing + n;
console.log(newBearing, 'newBearing');
var destination = turf.destination(point1, distance, newBearing, options);
let newP = destination.geometry.coordinates
newP.push(p[2])
// console.log(newP, 'destination');
const currentHeading = camera.heading;
// const currentHeading = camera.heading;
// const newHeading = currentHeading + Cesium.Math.toRadians(n);
// if (Math.abs(newBearing) < 9) {
// camera.setView({
// orientation: {
// heading: newHeading,
// pitch: camera.pitch,
// roll: camera.roll,
// },
// });
// return null
// }
// console.log(currentHeading,'currentHeading');
let bearingCamera = 0;
if (newBearing >= 0) {
bearingCamera = newBearing - 180
} else {
bearingCamera = newBearing + 180
}
// 将相机旋转到新的方向
camera.setView({
destination: Cesium.Cartesian3.fromDegrees(newP[0], newP[1], newP[2]),
orientation: {
heading: Cesium.Math.toRadians(bearingCamera),
pitch: camera.pitch,
roll: camera.roll,
},
});
}
Cartesian3_to_WGS84(point) {
var cartesian3 = new Cesium.Cartesian3(point.x, point.y, point.z);
var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
var lat = Cesium.Math.toDegrees(cartographic.latitude);
var lng = Cesium.Math.toDegrees(cartographic.longitude);
var alt = cartographic.height.toFixed(2);
return [
lng,
lat,
alt,
];
// return {
// lng: lng,
// lat: lat,
// alt: alt,
// };
}
//屏幕中点经纬度坐标
getScreenCenterCoordinates() {
// 范围对象
let coordinates = undefined;
// 得到当前三维场景
let scene = this.viewer.scene;
// 得到当前三维场景的椭球体
let ellipsoid = scene.globe.ellipsoid;
// 通过scene获取canvas长宽
// let canvas = scene.canvas;
// const canvasWidth = canvas.width;
// const canvasHeight = canvas.height;
改为获取body长宽 ,通过scene获取canvas在其他分辨率下存在兼容性问题
const canvasWidth = document.body.clientWidth;
const canvasHeight = document.body.clientHeight;
// canvas中点
let car3_center = this.viewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvasWidth / 2, canvasHeight / 2), ellipsoid);
let xcarto_center = undefined;
let ycarto_center = undefined;
// 当canvas中点在椭球体上
if (car3_center) {
let carto_center = ellipsoid.cartesianToCartographic(car3_center);
xcarto_center = Cesium.Math.toDegrees(carto_center.longitude);
ycarto_center = Cesium.Math.toDegrees(carto_center.latitude);
}
// 获取高度
let height = (this.viewer.camera.positionCartographic.height).toFixed(2);
coordinates = [xcarto_center, ycarto_center, height];
return coordinates;
}
addButtonTransformEvent(id, eventName) {
try {
let timer = null
let button = document.querySelector(id);
let eventNameString = eventName;
let findObj = this.btnSAddEventListenerName.find(ele => ele.id == id)
if (findObj) {
return
} {
this.btnSAddEventListenerName.push({
id: id,
eventName: eventName
})
}
if (button) {
if (this.clickEvent) {
this.buttonEvent[eventName] = {}
this.buttonEvent[eventName].up = () => {
if (eventNameString == "moveForward") {
this.moveCamera("Up");
} else if (eventNameString == "moveBackward") {
this.moveCamera("Down");
}
else if (eventNameString == "moveLeft") {
this.moveCamera("Left");
}
else if (eventNameString == "moveRight") {
this.moveCamera("Right");
}
else if (eventNameString == "rotation+") {
this.rotationCamera(this.rotationSpeed);
}
else if (eventNameString == "rotation-") {
this.rotationCamera(-this.rotationSpeed);
}
}
button.addEventListener("click", this.buttonEvent[eventName].up, false)
}
else {
this.buttonEvent[eventName] = {}
this.buttonEvent[eventName].up = () => {
if (timer) {
clearInterval(timer)
}
timer = setInterval(() => {
console.log('按钮被按下!');
if (eventNameString == "moveForward") {
this.moveCamera("Up");
} else if (eventNameString == "moveBackward") {
this.moveCamera("Down");
}
else if (eventNameString == "moveLeft") {
this.moveCamera("Left");
}
else if (eventNameString == "moveRight") {
this.moveCamera("Right");
}
else if (eventNameString == "rotation+") {
this.rotationCamera(this.rotationSpeed);
}
else if (eventNameString == "rotation-") {
this.rotationCamera(-this.rotationSpeed);
}
}, 30);
console.log(eventNameString, 'eventName');
}
button.addEventListener(this.downStart, this.buttonEvent[eventName].up, false)
this.buttonEvent[eventName].upEnd = () => {
clearInterval(timer)
console.log('按钮被松开!');
}
button.addEventListener(this.upEnd, this.buttonEvent[eventName].upEnd, false);
}
}
} catch (error) {
console.log(error, 'error');
}
}
}