• 软键盘控制cesium相机移动旋转


    1.有航向 类似于控制飞机飞行
     

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <script src="https://cesium.com/downloads/cesiumjs/releases/1.80/Build/Cesium/Cesium.js">script>
    8. <link rel="stylesheet"
    9. href="https://cesium.com/downloads/cesiumjs/releases/1.80/Build/Cesium/Widgets/widgets.css" />
    10. <script src="https://cdn.bootcdn.net/ajax/libs/Turf.js/6.5.0/turf.min.js">script>
    11. <script src="https://cdn.jsdelivr.net/npm/@dvgis/cesium-map/dist/cesium.map.min.js">script>
    12. <title>Documenttitle>
    13. <style>
    14. body,
    15. html {
    16. width: 100%;
    17. height: 100%;
    18. margin: 0;
    19. padding: 0;
    20. overflow: hidden;
    21. }
    22. #cesiumContainer {
    23. width: 100%;
    24. height: 100%;
    25. margin: 0;
    26. padding: 0;
    27. overflow: hidden;
    28. }
    29. .lonLat {
    30. position: fixed;
    31. width: 100%;
    32. bottom: 0;
    33. /* left: 50%; */
    34. color: aliceblue;
    35. text-align: center;
    36. }
    37. button:focus {
    38. outline: none;
    39. /* 取消选中时的轮廓边框 */
    40. box-shadow: none;
    41. /* 取消选中时的阴影效果 */
    42. }
    43. button {
    44. width: 80px;
    45. height: 50px;
    46. -webkit-user-select: none;
    47. /* Chrome, Safari, Opera */
    48. -moz-user-select: none;
    49. /* Firefox */
    50. -ms-user-select: none;
    51. /* Internet Explorer/Edge */
    52. user-select: none;
    53. /* 此规则适用于大多数浏览器 */
    54. }
    55. style>
    56. head>
    57. <body>
    58. <div id="cesiumContainer">div>
    59. <div class="lonLat">
    60. <button class="btn1">button>
    61. <button class="btn2">button>
    62. <button class="btn3">button>
    63. <button class="btn4">button>
    64. <button class="rotation1">旋转heading+button>
    65. <button class="rotation2">旋转heading-button>
    66. <button class="openC">开启button>
    67. <button class="closeC">关闭button>
    68. div>
    69. <script>
    70. // document.oncontextmenu = new Function("event.returnValue=false");
    71. // document.onselectstart = new Function("event.returnValue=false");
    72. // document.addEventListener("keydown", function (e) {
    73. // console.log(e.key);
    74. // if (e.key == "F12") {
    75. // e.preventDefault(); // 如果按下键F12,阻止事件
    76. // }
    77. // });
    78. var viewer = new Cesium.Viewer("cesiumContainer", {
    79. geocoder: false, // 位置查找工具
    80. timeline: false, // 底部时间线
    81. homeButton: false, // 视角返回初始位置
    82. fullscreenButton: false, // 全屏
    83. animation: false, // 左下角仪表盘(动画器件)
    84. sceneModePicker: false, // 选择视角的模式(球体、平铺、斜视平铺)
    85. navigationHelpButton: false, //导航帮助按钮
    86. targetFrameRate: 30,
    87. imageryProvider: new Cesium.SingleTileImageryProvider({
    88. url: "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=",
    89. }),
    90. baseLayerPicker: false,
    91. });
    92. // 不显示底图
    93. // viewer.imageryLayers.get(0).show = false;
    94. // 去除logo
    95. viewer.cesiumWidget.creditContainer.style.display = "none";
    96. // 高德
    97. var optionsG = {
    98. style: 'img', // style: img、elec、cva//地标 网路
    99. crs: 'WGS84', // 使用84坐标系,默认为:GCJ02
    100. maximumLevel: 18, // 设置最大级别
    101. // minimumLevel: 5 // 设置最小级别
    102. }
    103. viewer.imageryLayers.add(new Cesium.ImageryLayer(new AmapImageryProvider(optionsG)))
    104. // // 腾讯
    105. // var optionsT = {
    106. // style: 'img' //style: img、1:经典
    107. // }
    108. // viewer.imageryLayers.add(new Cesium.ImageryLayer(new TencentImageryProvider(optionsT)))
    109. // 百度
    110. // var optionsBI = {
    111. // style: 'img', // style: img、vec//地标 网路、normal、dark
    112. // crs: 'WGS84' // 使用84坐标系,默认为:BD09
    113. // }
    114. // viewer.imageryLayers.add(new Cesium.ImageryLayer(new BaiduImageryProvider(optionsBI)))
    115. var optionsB = {
    116. style: 'vec', // style: img、vec//地标 网路、normal、dark
    117. crs: 'WGS84', // 使用84坐标系,默认为:BD09
    118. maximumLevel: 18, // 设置最大级别
    119. // minimumLevel: 5 // 设置最小级别
    120. }
    121. viewer.imageryLayers.add(new Cesium.ImageryLayer(new BaiduImageryProvider(optionsB)))
    122. viewer.screenSpaceEventHandler.setInputAction(movement => {
    123. // 方式 1
    124. var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
    125. if (cartesian) {
    126. var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    127. var longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(8);
    128. var latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(8);
    129. let height = this.viewer.camera.positionCartographic.height.toFixed(2);
    130. // var point = GPS.bd09_To_Gcj02(latitudeString,longitudeString)
    131. // this.nowPosition = point.lon + ',' + point.lat + "," + height
    132. // console.log(this.nowPosition,'this.nowPosition');
    133. this.nowPosition = longitudeString + ',' + latitudeString + "," + height
    134. this.nowPositionheight = height
    135. console.log("LongitudeAndLatitude: " + longitudeString + "," + latitudeString + "," + height);
    136. var h = this.viewer.scene.camera.heading;
    137. var p = this.viewer.scene.camera.pitch;
    138. var r = this.viewer.scene.camera.roll;
    139. console.log("headingPitchRoll: " + h + "," + p + "," + r);
    140. }
    141. }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    142. let pointDestination = Cesium.Cartesian3.fromDegrees(116.40069537, 39.96790221, 1500);//视野点
    143. viewer.scene.camera.flyTo({
    144. destination: pointDestination,
    145. orientation: {
    146. heading: 6.283185307179586,
    147. pitch: -1.5707963267948966,
    148. roll: 0
    149. }
    150. })
    151. class CameraNavigation {
    152. constructor(viewer) {
    153. this.viewer = viewer;
    154. this.flyDuration = 0.5
    155. this.clickEvent = true;
    156. this.moveEndHandler = null;
    157. this.speed = null
    158. this.moveSpeed = null;
    159. this.height = null;
    160. this.buttonEvent = {};
    161. this.rotationSpeed = 2
    162. this.deviceType = this.getDeviceType();
    163. this.initControl()
    164. this.btnSAddEventListenerName = []
    165. }
    166. getDeviceType() {
    167. const userAgent = navigator.userAgent;
    168. console.log(userAgent);
    169. if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
    170. return "平板";
    171. } else if (
    172. /(mobi|opera mini|iphone|ipod|android|blackberry|windows phone)/i.test(
    173. userAgent
    174. )
    175. ) {
    176. return "手机";
    177. } else {
    178. return "电脑";
    179. }
    180. }
    181. initControl() {
    182. this.downStart = 'touchstart';
    183. this.upEnd = 'touchend';
    184. if (this.deviceType == "电脑") {
    185. this.downStart = "mousedown"
    186. this.upEnd = "mouseup"
    187. }
    188. console.log(this.upEnd, this.downStart);
    189. }
    190. setupEventListeners() {
    191. if (this.moveSpeed) {
    192. this.speed = this.moveSpeed
    193. }
    194. let currentHeightInit = this.viewer.camera.positionCartographic.height;
    195. this.height = Math.round(currentHeightInit);
    196. // 添加高度变化监听事件
    197. this.moveEndHandler = () => {
    198. console.log(111);
    199. const currentHeight = this.viewer.camera.positionCartographic.height;
    200. this.height = Math.round(currentHeight);
    201. if (!this.moveSpeed) {
    202. this.speed = this.height / 100
    203. } else {
    204. this.speed = this.moveSpeed
    205. }
    206. }
    207. this.viewer.camera.moveEnd.addEventListener(this.moveEndHandler);
    208. console.log(this.height, 'this.height');
    209. }
    210. setupCameraNavigation() {
    211. // 定义事件处理函数
    212. function handleKeyDown(event) {
    213. console.log(event.key);
    214. switch (event.key) {
    215. // case 'ArrowUp' || 'w':
    216. case 'w':
    217. this.moveCamera("Up");
    218. break;
    219. // case 'ArrowDown' || 'd':
    220. case 's':
    221. this.moveCamera("Down");
    222. break;
    223. // case 'ArrowLeft' || 's':
    224. case 'a':
    225. this.moveCamera("Left");
    226. break;
    227. // case 'ArrowRight' || 'a':
    228. case 'd':
    229. this.moveCamera("Right");
    230. break;
    231. case 'q':
    232. this.rotationCamera(10);
    233. break;
    234. case 'e':
    235. this.rotationCamera(-10);
    236. break;
    237. default:
    238. break;
    239. }
    240. }
    241. // 添加键盘按下事件监听器
    242. document.addEventListener('keydown', handleKeyDown.bind(this));
    243. }
    244. removeCameraNavigation() {
    245. try {
    246. this.btnSAddEventListenerName.forEach(ele => {
    247. if (this.clickEvent) {
    248. document.querySelector(ele.id).removeEventListener('click', this.buttonEvent[ele.eventName].up, false)
    249. } else {
    250. document.querySelector(ele.id).removeEventListener(this.downStart, this.buttonEvent[ele.eventName].up, false)
    251. document.querySelector(ele.id).removeEventListener(this.upEnd, this.buttonEvent[ele.eventName].upEnd, false)
    252. }
    253. })
    254. // 移除键盘按下事件监听器
    255. // document.removeEventListener('keydown', this.handleKeyDown);
    256. // 取消高度变化监听事件
    257. this.viewer.camera.moveEnd.removeEventListener(this.moveEndHandler);
    258. this.btnSAddEventListenerName = []
    259. this.buttonEvent = {}
    260. } catch (error) {
    261. console.log(error, 'error');
    262. }
    263. }
    264. moveCamera(type = 'Up') {
    265. try {
    266. // 获取当前Cesium相机
    267. const camera = this.viewer.camera;
    268. // 获取当前相机的位置和方向
    269. const currentPosition = camera.positionCartographic.clone();
    270. const currentHeading = camera.heading;
    271. // 定义移动的距离和方向
    272. const distance = this.speed; // 1000米示例距离
    273. let bearing = Cesium.Math.toDegrees(currentHeading); // 使用当前方向
    274. switch (type) {
    275. case 'Up': // 向上移动
    276. bearing = Cesium.Math.toDegrees(currentHeading)
    277. break;
    278. case 'Down': // 向下移动
    279. bearing = Cesium.Math.toDegrees(currentHeading - Math.PI); // 使用当前方向
    280. break;
    281. case 'Left': // 向左移动
    282. bearing = Cesium.Math.toDegrees(currentHeading - Math.PI / 2); // 使用当前方向
    283. break;
    284. case 'Right': // 向右移动
    285. bearing = Cesium.Math.toDegrees(currentHeading + Math.PI / 2); // 使用当前方向
    286. break;
    287. default:
    288. break;
    289. }
    290. // 使用Turf.js计算新位置
    291. const destination = turf.destination(
    292. turf.point([Cesium.Math.toDegrees(currentPosition.longitude), Cesium.Math.toDegrees(currentPosition.latitude)]),
    293. distance,
    294. bearing,
    295. { units: 'meters' }
    296. );
    297. // 将新位置转换为Cesium坐标
    298. const newCartesian = Cesium.Cartesian3.fromDegrees(destination.geometry.coordinates[0], destination.geometry.coordinates[1], this.height);
    299. // 设置相机位置
    300. // camera.position = newCartesian;
    301. camera.flyTo({
    302. destination: newCartesian,
    303. orientation: {
    304. heading: camera.heading,
    305. pitch: camera.pitch,
    306. roll: camera.roll
    307. },
    308. duration: this.flyDuration
    309. })
    310. } catch (error) {
    311. console.log(error, 'error');
    312. }
    313. }
    314. // rotationCamera(n) {
    315. // // 获取当前相机
    316. // const camera = this.viewer.camera;
    317. // // 获取当前相机的方向(heading)
    318. // const currentHeading = camera.heading;
    319. // // 设置旋转后的方向(顺时针旋转10度)
    320. // const newHeading = currentHeading + Cesium.Math.toRadians(n);
    321. // // 将相机旋转到新的方向
    322. // camera.setView({
    323. // orientation: {
    324. // heading: newHeading,
    325. // pitch: camera.pitch,
    326. // roll: camera.roll,
    327. // },
    328. // });
    329. // }
    330. rotationCamera(n) {
    331. let centerScreen = this.getScreenCenterCoordinates();
    332. console.log(centerScreen, 'getScreenCenterCoordinates');
    333. // 获取当前相机
    334. const camera = this.viewer.camera;
    335. // console.log(camera.position, 'camera');
    336. let p = this.Cartesian3_to_WGS84(camera.position)
    337. // console.log(p, 'ppp');
    338. // 获取当前相机的方向(heading)
    339. var point1 = turf.point(centerScreen);
    340. var point2 = turf.point(p);
    341. var options = { units: 'meters' };
    342. var bearing = turf.bearing(point1, point2);
    343. var bearing1 = turf.bearing(point2, point1);
    344. // console.log(bearing, bearing1, 'bearing1bearing1');
    345. var distance = turf.distance(point1, point2, options);
    346. // console.log(Cesium.Math.toRadians(n), 'Cesium.Math.toRadians(n)Cesium.Math.toRadians(n)');
    347. let newBearing = bearing - Cesium.Math.toRadians(n);
    348. console.log(newBearing, 'newBearing');
    349. var destination = turf.destination(point1, distance, newBearing, options);
    350. let newP = destination.geometry.coordinates
    351. newP.push(p[2])
    352. // console.log(newP, 'destination');
    353. const currentHeading = camera.heading;
    354. const newHeading = currentHeading + Cesium.Math.toRadians(n / 15);
    355. if (Math.abs(newBearing) < 4) {
    356. camera.setView({
    357. orientation: {
    358. heading: newHeading,
    359. pitch: camera.pitch,
    360. roll: camera.roll,
    361. },
    362. });
    363. return null
    364. }
    365. // console.log(currentHeading,'currentHeading');
    366. let bearingCamera = 0;
    367. if (newBearing >= 0) {
    368. bearingCamera = newBearing - 180
    369. } else {
    370. bearingCamera = newBearing + 180
    371. }
    372. // 将相机旋转到新的方向
    373. camera.setView({
    374. destination: Cesium.Cartesian3.fromDegrees(newP[0], newP[1], newP[2]),
    375. orientation: {
    376. heading: Cesium.Math.toRadians(bearingCamera),
    377. pitch: camera.pitch,
    378. roll: camera.roll,
    379. },
    380. });
    381. }
    382. Cartesian3_to_WGS84(point) {
    383. var cartesian3 = new Cesium.Cartesian3(point.x, point.y, point.z);
    384. var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
    385. var lat = Cesium.Math.toDegrees(cartographic.latitude);
    386. var lng = Cesium.Math.toDegrees(cartographic.longitude);
    387. var alt = cartographic.height.toFixed(2);
    388. return [
    389. lng,
    390. lat,
    391. alt,
    392. ];
    393. // return {
    394. // lng: lng,
    395. // lat: lat,
    396. // alt: alt,
    397. // };
    398. }
    399. //屏幕中点经纬度坐标
    400. getScreenCenterCoordinates() {
    401. // 范围对象
    402. let coordinates = undefined;
    403. // 得到当前三维场景
    404. let scene = this.viewer.scene;
    405. // 得到当前三维场景的椭球体
    406. let ellipsoid = scene.globe.ellipsoid;
    407. // 通过scene获取canvas长宽
    408. // let canvas = scene.canvas;
    409. // const canvasWidth = canvas.width;
    410. // const canvasHeight = canvas.height;
    411. 改为获取body长宽 ,通过scene获取canvas在其他分辨率下存在兼容性问题
    412. const canvasWidth = document.body.clientWidth;
    413. const canvasHeight = document.body.clientHeight;
    414. // canvas中点
    415. let car3_center = this.viewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvasWidth / 2, canvasHeight / 2), ellipsoid);
    416. let xcarto_center = undefined;
    417. let ycarto_center = undefined;
    418. // 当canvas中点在椭球体上
    419. if (car3_center) {
    420. let carto_center = ellipsoid.cartesianToCartographic(car3_center);
    421. xcarto_center = Cesium.Math.toDegrees(carto_center.longitude);
    422. ycarto_center = Cesium.Math.toDegrees(carto_center.latitude);
    423. }
    424. // 获取高度
    425. let height = (this.viewer.camera.positionCartographic.height).toFixed(2);
    426. coordinates = [xcarto_center, ycarto_center, height];
    427. return coordinates;
    428. }
    429. addButtonTransformEvent(id, eventName) {
    430. try {
    431. let timer = null
    432. let button = document.querySelector(id);
    433. let eventNameString = eventName;
    434. let findObj = this.btnSAddEventListenerName.find(ele => ele.id == id)
    435. if (findObj) {
    436. return
    437. } {
    438. this.btnSAddEventListenerName.push({
    439. id: id,
    440. eventName: eventName
    441. })
    442. }
    443. if (button) {
    444. if (this.clickEvent) {
    445. this.buttonEvent[eventName] = {}
    446. this.buttonEvent[eventName].up = () => {
    447. if (eventNameString == "moveForward") {
    448. this.moveCamera("Up");
    449. } else if (eventNameString == "moveBackward") {
    450. this.moveCamera("Down");
    451. }
    452. else if (eventNameString == "moveLeft") {
    453. this.moveCamera("Left");
    454. }
    455. else if (eventNameString == "moveRight") {
    456. this.moveCamera("Right");
    457. }
    458. else if (eventNameString == "rotation+") {
    459. this.rotationCamera(this.rotationSpeed);
    460. }
    461. else if (eventNameString == "rotation-") {
    462. this.rotationCamera(-this.rotationSpeed);
    463. }
    464. }
    465. button.addEventListener("click", this.buttonEvent[eventName].up, false)
    466. }
    467. else {
    468. this.buttonEvent[eventName] = {}
    469. this.buttonEvent[eventName].up = () => {
    470. if (timer) {
    471. clearInterval(timer)
    472. }
    473. timer = setInterval(() => {
    474. console.log('按钮被按下!');
    475. if (eventNameString == "moveForward") {
    476. this.moveCamera("Up");
    477. } else if (eventNameString == "moveBackward") {
    478. this.moveCamera("Down");
    479. }
    480. else if (eventNameString == "moveLeft") {
    481. this.moveCamera("Left");
    482. }
    483. else if (eventNameString == "moveRight") {
    484. this.moveCamera("Right");
    485. }
    486. else if (eventNameString == "rotation+") {
    487. this.rotationCamera(this.rotationSpeed);
    488. }
    489. else if (eventNameString == "rotation-") {
    490. this.rotationCamera(-this.rotationSpeed);
    491. }
    492. }, 30);
    493. console.log(eventNameString, 'eventName');
    494. }
    495. button.addEventListener(this.downStart, this.buttonEvent[eventName].up, false)
    496. this.buttonEvent[eventName].upEnd = () => {
    497. clearInterval(timer)
    498. console.log('按钮被松开!');
    499. }
    500. button.addEventListener(this.upEnd, this.buttonEvent[eventName].upEnd, false);
    501. }
    502. }
    503. } catch (error) {
    504. console.log(error, 'error');
    505. }
    506. }
    507. }
    508. const cameraNavigation = new CameraNavigation(viewer);
    509. document.querySelector('.openC').addEventListener("click", () => {
    510. // cameraNavigation.clickEvent = false;
    511. cameraNavigation.moveSpeed = 100 // 移动速度 默认是当前相机高度/100的速度
    512. cameraNavigation.rotationSpeed = 180// 旋转速度 默认是2度每次
    513. cameraNavigation.setupEventListeners();
    514. cameraNavigation.addButtonTransformEvent('.btn1', 'moveForward')
    515. cameraNavigation.addButtonTransformEvent('.btn2', 'moveBackward')
    516. cameraNavigation.addButtonTransformEvent('.btn3', 'moveLeft')
    517. cameraNavigation.addButtonTransformEvent('.btn4', 'moveRight')
    518. cameraNavigation.addButtonTransformEvent('.rotation1', 'rotation+')
    519. cameraNavigation.addButtonTransformEvent('.rotation2', 'rotation-')
    520. });
    521. document.querySelector('.closeC').addEventListener("click", () => {
    522. cameraNavigation.removeCameraNavigation();
    523. });
    524. script>
    525. body>
    526. html>

    2.

     2. 同高度飞行,通过航向角计算封装
     

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <script src="https://cesium.com/downloads/cesiumjs/releases/1.80/Build/Cesium/Cesium.js">script>
    8. <link rel="stylesheet"
    9. href="https://cesium.com/downloads/cesiumjs/releases/1.80/Build/Cesium/Widgets/widgets.css" />
    10. <script src="https://cdn.bootcdn.net/ajax/libs/Turf.js/6.5.0/turf.min.js">script>
    11. <script src="https://cdn.jsdelivr.net/npm/@dvgis/cesium-map/dist/cesium.map.min.js">script>
    12. <title>Documenttitle>
    13. <style>
    14. body,
    15. html {
    16. width: 100%;
    17. height: 100%;
    18. margin: 0;
    19. padding: 0;
    20. overflow: hidden;
    21. }
    22. #cesiumContainer {
    23. width: 100%;
    24. height: 100%;
    25. margin: 0;
    26. padding: 0;
    27. overflow: hidden;
    28. }
    29. .lonLat {
    30. position: fixed;
    31. width: 100%;
    32. bottom: 0;
    33. /* left: 50%; */
    34. color: aliceblue;
    35. text-align: center;
    36. }
    37. button:focus {
    38. outline: none;
    39. /* 取消选中时的轮廓边框 */
    40. box-shadow: none;
    41. /* 取消选中时的阴影效果 */
    42. }
    43. button {
    44. width: 80px;
    45. height: 50px;
    46. -webkit-user-select: none;
    47. /* Chrome, Safari, Opera */
    48. -moz-user-select: none;
    49. /* Firefox */
    50. -ms-user-select: none;
    51. /* Internet Explorer/Edge */
    52. user-select: none;
    53. /* 此规则适用于大多数浏览器 */
    54. }
    55. style>
    56. head>
    57. <body>
    58. <div id="cesiumContainer">div>
    59. <div class="lonLat">
    60. <div>
    61. <button class="openC">开启button>
    62. <button class="closeC">关闭button>
    63. div>
    64. <button class="btn1">button>
    65. <button class="btn2">button>
    66. <button class="btn3">button>
    67. <button class="btn4">button>
    68. <button class="rotation1">旋转heading+button>
    69. <button class="rotation2">旋转heading-button>
    70. div>
    71. <script>
    72. // document.oncontextmenu = new Function("event.returnValue=false");
    73. // document.onselectstart = new Function("event.returnValue=false");
    74. // document.addEventListener("keydown", function (e) {
    75. // console.log(e.key);
    76. // if (e.key == "F12") {
    77. // e.preventDefault(); // 如果按下键F12,阻止事件
    78. // }
    79. // });
    80. // function getDeviceType() {
    81. // const userAgent = navigator.userAgent;
    82. // console.log(userAgent);
    83. // if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
    84. // return "平板";
    85. // } else if (
    86. // /(mobi|opera mini|iphone|ipod|android|blackberry|windows phone)/i.test(
    87. // userAgent
    88. // )
    89. // ) {
    90. // return "手机";
    91. // } else {
    92. // return "电脑";
    93. // }
    94. // }
    95. // // 使用示例
    96. // const deviceType = getDeviceType();
    97. // console.log("设备类型:", deviceType);
    98. var viewer = new Cesium.Viewer("cesiumContainer", {
    99. geocoder: false, // 位置查找工具
    100. timeline: false, // 底部时间线
    101. homeButton: false, // 视角返回初始位置
    102. fullscreenButton: false, // 全屏
    103. animation: false, // 左下角仪表盘(动画器件)
    104. sceneModePicker: false, // 选择视角的模式(球体、平铺、斜视平铺)
    105. navigationHelpButton: false, //导航帮助按钮
    106. targetFrameRate: 30,
    107. imageryProvider: new Cesium.SingleTileImageryProvider({
    108. url: "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=",
    109. }),
    110. baseLayerPicker: false,
    111. });
    112. // 不显示底图
    113. // viewer.imageryLayers.get(0).show = false;
    114. // 去除logo
    115. viewer.cesiumWidget.creditContainer.style.display = "none";
    116. // 高德
    117. var optionsG = {
    118. style: 'img', // style: img、elec、cva//地标 网路
    119. crs: 'WGS84', // 使用84坐标系,默认为:GCJ02
    120. maximumLevel: 18, // 设置最大级别
    121. // minimumLevel: 5 // 设置最小级别
    122. }
    123. viewer.imageryLayers.add(new Cesium.ImageryLayer(new AmapImageryProvider(optionsG)))
    124. // // 腾讯
    125. // var optionsT = {
    126. // style: 'img' //style: img、1:经典
    127. // }
    128. // viewer.imageryLayers.add(new Cesium.ImageryLayer(new TencentImageryProvider(optionsT)))
    129. // 百度
    130. // var optionsBI = {
    131. // style: 'img', // style: img、vec//地标 网路、normal、dark
    132. // crs: 'WGS84' // 使用84坐标系,默认为:BD09
    133. // }
    134. // viewer.imageryLayers.add(new Cesium.ImageryLayer(new BaiduImageryProvider(optionsBI)))
    135. var optionsB = {
    136. style: 'vec', // style: img、vec//地标 网路、normal、dark
    137. crs: 'WGS84', // 使用84坐标系,默认为:BD09
    138. maximumLevel: 18, // 设置最大级别
    139. // minimumLevel: 5 // 设置最小级别
    140. }
    141. viewer.imageryLayers.add(new Cesium.ImageryLayer(new BaiduImageryProvider(optionsB)))
    142. viewer.screenSpaceEventHandler.setInputAction(movement => {
    143. // 方式 1
    144. var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
    145. if (cartesian) {
    146. var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    147. var longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(8);
    148. var latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(8);
    149. let height = this.viewer.camera.positionCartographic.height.toFixed(2);
    150. // var point = GPS.bd09_To_Gcj02(latitudeString,longitudeString)
    151. // this.nowPosition = point.lon + ',' + point.lat + "," + height
    152. // console.log(this.nowPosition,'this.nowPosition');
    153. this.nowPosition = longitudeString + ',' + latitudeString + "," + height
    154. this.nowPositionheight = height
    155. console.log("LongitudeAndLatitude: " + longitudeString + "," + latitudeString + "," + height);
    156. var h = this.viewer.scene.camera.heading;
    157. var p = this.viewer.scene.camera.pitch;
    158. var r = this.viewer.scene.camera.roll;
    159. console.log("headingPitchRoll: " + h + "," + p + "," + r);
    160. }
    161. }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    162. let pointDestination = Cesium.Cartesian3.fromDegrees(116.40069537, 39.96790221, 1500);//视野点
    163. viewer.scene.camera.flyTo({
    164. destination: pointDestination,
    165. orientation: {
    166. heading: 6.283185307179586,
    167. pitch: -1.5707963267948966,
    168. roll: 0
    169. }
    170. })
    171. class CameraNavigation {
    172. constructor(viewer) {
    173. this.viewer = viewer;
    174. this.moveEndHandler = null;
    175. this.speed = null
    176. this.moveSpeed = null;
    177. this.height = null;
    178. this.buttonEvent = {};
    179. this.rotationSpeed = 2
    180. this.deviceType = this.getDeviceType();
    181. this.initControl()
    182. this.btnSAddEventListenerName = []
    183. }
    184. getDeviceType() {
    185. const userAgent = navigator.userAgent;
    186. console.log(userAgent);
    187. if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
    188. return "平板";
    189. } else if (
    190. /(mobi|opera mini|iphone|ipod|android|blackberry|windows phone)/i.test(
    191. userAgent
    192. )
    193. ) {
    194. return "手机";
    195. } else {
    196. return "电脑";
    197. }
    198. }
    199. initControl() {
    200. this.downStart = 'touchstart';
    201. this.upEnd = 'touchend';
    202. if (this.deviceType == "电脑") {
    203. this.downStart = "mousedown"
    204. this.upEnd = "mouseup"
    205. }
    206. console.log( this.upEnd, this.downStart);
    207. }
    208. setupEventListeners() {
    209. let currentHeightInit = this.viewer.camera.positionCartographic.height;
    210. this.height = Math.round(currentHeightInit);
    211. // 添加高度变化监听事件
    212. this.moveEndHandler = () => {
    213. console.log(111);
    214. const currentHeight = this.viewer.camera.positionCartographic.height;
    215. this.height = Math.round(currentHeight);
    216. if (!this.moveSpeed) {
    217. this.speed = this.height/100
    218. }else {
    219. this.speed = this.moveSpeed
    220. }
    221. }
    222. this.viewer.camera.moveEnd.addEventListener(this.moveEndHandler);
    223. console.log(this.height,'this.height');
    224. }
    225. setupCameraNavigation() {
    226. // 定义事件处理函数
    227. this.handleKeyDown =(event)=> {
    228. console.log(event.key);
    229. switch (event.key) {
    230. // case 'ArrowUp' || 'w':
    231. case 'w':
    232. this.moveCamera("Up");
    233. break;
    234. // case 'ArrowDown' || 'd':
    235. case 's':
    236. this.moveCamera("Down");
    237. break;
    238. // case 'ArrowLeft' || 's':
    239. case 'a':
    240. this.moveCamera("Left");
    241. break;
    242. // case 'ArrowRight' || 'a':
    243. case 'd':
    244. this.moveCamera("Right");
    245. break;
    246. case 'q':
    247. this.rotationCamera(10);
    248. break;
    249. case 'e':
    250. this.rotationCamera(-10);
    251. break;
    252. default:
    253. break;
    254. }
    255. }
    256. // 添加键盘按下事件监听器
    257. document.addEventListener('keydown', this.handleKeyDown);
    258. }
    259. removeCameraNavigation() {
    260. this.btnSAddEventListenerName.forEach(ele=>{
    261. document.querySelector(ele.id).removeEventListener(this.downStart,this.buttonEvent[ele.eventName].up, false)
    262. document.querySelector(ele.id).removeEventListener(this.upEnd,this.buttonEvent[ele.eventName].upEnd, false)
    263. })
    264. // 移除键盘按下事件监听器
    265. if (this.handleKeyDown) {
    266. document.removeEventListener('keydown', this.handleKeyDown);
    267. }
    268. // 取消高度变化监听事件
    269. this.viewer.camera.moveEnd.removeEventListener(this.moveEndHandler);
    270. this.btnSAddEventListenerName =[]
    271. this.buttonEvent = {}
    272. }
    273. moveCamera(type = 'Up') {
    274. // 获取当前Cesium相机
    275. const camera = this.viewer.camera;
    276. // 获取当前相机的位置和方向
    277. const currentPosition = camera.positionCartographic.clone();
    278. const currentHeading = camera.heading;
    279. // 定义移动的距离和方向
    280. const distance = this.speed; // 1000米示例距离
    281. let bearing = Cesium.Math.toDegrees(currentHeading); // 使用当前方向
    282. switch (type) {
    283. case 'Up': // 向上移动
    284. bearing = Cesium.Math.toDegrees(currentHeading)
    285. break;
    286. case 'Down': // 向下移动
    287. bearing = Cesium.Math.toDegrees(currentHeading - Math.PI); // 使用当前方向
    288. break;
    289. case 'Left': // 向左移动
    290. bearing = Cesium.Math.toDegrees(currentHeading - Math.PI / 2); // 使用当前方向
    291. break;
    292. case 'Right': // 向右移动
    293. bearing = Cesium.Math.toDegrees(currentHeading + Math.PI / 2); // 使用当前方向
    294. break;
    295. default:
    296. break;
    297. }
    298. // 使用Turf.js计算新位置
    299. const destination = turf.destination(
    300. turf.point([Cesium.Math.toDegrees(currentPosition.longitude), Cesium.Math.toDegrees(currentPosition.latitude)]),
    301. distance,
    302. bearing,
    303. { units: 'meters' }
    304. );
    305. // 将新位置转换为Cesium坐标
    306. const newCartesian = Cesium.Cartesian3.fromDegrees(destination.geometry.coordinates[0], destination.geometry.coordinates[1], this.height);
    307. // 设置相机位置
    308. camera.position = newCartesian;
    309. }
    310. rotationCamera(n) {
    311. // 获取当前相机
    312. const camera = this.viewer.camera;
    313. // 获取当前相机的方向(heading)
    314. const currentHeading = camera.heading;
    315. // 设置旋转后的方向(顺时针旋转10度)
    316. const newHeading = currentHeading + Cesium.Math.toRadians(n);
    317. // 将相机旋转到新的方向
    318. camera.setView({
    319. orientation: {
    320. heading: newHeading,
    321. pitch: camera.pitch,
    322. roll: camera.roll,
    323. },
    324. });
    325. }
    326. addButtonTransformEvent(id, eventName) {
    327. let timer = null
    328. let button = document.querySelector(id);
    329. let eventNameString =eventName;
    330. let findObj = this.btnSAddEventListenerName.find(ele=>ele.id== id)
    331. if (findObj) {
    332. return
    333. }{
    334. this.btnSAddEventListenerName.push({
    335. id:id,
    336. eventName:eventName
    337. })
    338. }
    339. if (button) {
    340. this.buttonEvent[eventName] = {}
    341. this.buttonEvent[eventName].up = () => {
    342. if (timer) {
    343. clearInterval(timer)
    344. }
    345. timer = setInterval(() => {
    346. console.log('按钮被按下!');
    347. if (eventNameString == "moveForward") {
    348. this.moveCamera("Up");
    349. }else if (eventNameString == "moveBackward") {
    350. this.moveCamera("Down");
    351. }
    352. else if (eventNameString == "moveLeft") {
    353. this.moveCamera("Left");
    354. }
    355. else if (eventNameString == "moveRight") {
    356. this.moveCamera("Right");
    357. }
    358. else if (eventNameString == "rotation+") {
    359. this.rotationCamera(this.rotationSpeed) ;
    360. }
    361. else if (eventNameString == "rotation-") {
    362. this.rotationCamera(-this.rotationSpeed) ;
    363. }
    364. }, 30);
    365. console.log(eventNameString, 'eventName');
    366. }
    367. button.addEventListener(this.downStart,this.buttonEvent[eventName].up, false)
    368. this.buttonEvent[eventName].upEnd = () => {
    369. clearInterval(timer)
    370. console.log('按钮被松开!');
    371. }
    372. button.addEventListener(this.upEnd,this.buttonEvent[eventName].upEnd, false);
    373. }
    374. }
    375. }
    376. // 使用示例
    377. const cameraNavigation = new CameraNavigation(viewer);
    378. document.querySelector('.openC').addEventListener("click", () => {
    379. cameraNavigation.setupCameraNavigation()
    380. // cameraNavigation.moveSpeed = 100 // 移动速度 默认是当前相机高度/100的速度
    381. cameraNavigation.rotationSpeed = 0.2// 旋转速度 默认是2度每次
    382. cameraNavigation.setupEventListeners();
    383. cameraNavigation.addButtonTransformEvent('.btn1', 'moveForward')
    384. cameraNavigation.addButtonTransformEvent('.btn2', 'moveBackward')
    385. cameraNavigation.addButtonTransformEvent('.btn3', 'moveLeft')
    386. cameraNavigation.addButtonTransformEvent('.btn4', 'moveRight')
    387. cameraNavigation.addButtonTransformEvent('.rotation1', 'rotation+')
    388. cameraNavigation.addButtonTransformEvent('.rotation2', 'rotation-')
    389. });
    390. document.querySelector('.closeC').addEventListener("click", () => {
    391. cameraNavigation.removeCameraNavigation();
    392. });
    393. script>
    394. body>
    395. html>

  • 相关阅读:
    如何用 Llama 3 免费本地 AI 分析数据和可视化?
    自动拟人对话机器人在客户服务方面起了什么作用?
    DSPE-PEG-GE11,GE11-PEG-DSPE,磷脂-聚乙二醇-靶向多肽GE11
    玫琳凯公司助力大自然保护协会和全球合作伙伴在联合国海洋大会上举办活动,讨论改善海洋保护区
    5. 【线索二叉树】的由来、基本概念、结构体定义、三种遍历线索化、线索二叉树找前驱/后继
    编写Ansible角色实现分布式LNMP安装
    [附源码]SSM计算机毕业设计医院仪器设备管理系统JAVA
    DAY34:XXE 漏洞基础
    Elasticsearch实战(十八)--ES搜索Doc Values/Fielddata 正排索引 深入解析
    k8s、调度约束
  • 原文地址:https://blog.csdn.net/songJunFeng1/article/details/132862571