index.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. <template>
  2. <div class="container">
  3. <el-row id="earth" style="height: 100%; width: 100%; display: flex; position: relative">
  4. <el-col style="height: 100%; position: relative" :span="this.leftwidth">
  5. <div class="main-layout" v-on:mouseover="changeActive('2D')" @mousemove="getMouseLocation">
  6. <div id="2DcesiumContainer" class="map"></div>
  7. </div>
  8. </el-col>
  9. <el-col style="height: 100%; position: relative" :span="24 - this.leftwidth">
  10. <div class="main-layout" v-on:mouseover="changeActive('3D')" @mousemove="getMouseLocation">
  11. <div id="3DcesiumContainer" class="map"></div>
  12. </div>
  13. </el-col>
  14. <el-tabs type="border-card" v-model="activeName" tab-position="left" class="menu" :stretch="true"
  15. @tab-click="legendClick">
  16. <el-tab-pane name="fouth">
  17. <el-tooltip placement="right" effect="light" slot="label">
  18. <span slot="content" class="item">想定</span>
  19. <span><i class="el-icon-house"></i></span>
  20. </el-tooltip>
  21. <el-table :data="situation">
  22. <el-table-column label="名称" prop="xdname" width="150px"></el-table-column>
  23. <el-table-column label="操作" align="center">
  24. <template slot-scope="scope">
  25. <el-button type="primary" @click="getJson(scope.row)">导入</el-button>
  26. <!-- <el-button type="primary" @click="saveJson()">保存</el-button> -->
  27. </template>
  28. </el-table-column>
  29. </el-table>
  30. </el-tab-pane>
  31. </el-tabs>
  32. <div class="buttons">
  33. <el-button icon="el-icon-full-screen" circle @click="ismax()"></el-button>
  34. <el-button icon="el-icon-house" circle @click="home()"></el-button>
  35. <el-button icon="el-icon-plus" circle @click="big()"></el-button>
  36. <el-button icon="el-icon-minus" circle @click="small()"></el-button>
  37. </div>
  38. </el-row>
  39. <!-- <TimeLine :showLayers="showLayers" :timeDataArray="timeDataArray" class="TimeLine"></TimeLine> -->
  40. </div>
  41. </template>
  42. <script>
  43. import screenfull from "screenfull";
  44. import fireController from "@/api/fireController.js";
  45. import { getToken } from "@/utils";
  46. import axios from "axios";
  47. import satelliteModel from 'public/static/model/satelite1.glb';
  48. import TimeLine from '@/components/TimeLine/index.vue';
  49. import missileModel from 'public/static/model/basic_missle.glb';
  50. import thaadModel from 'public/static/model/anti-aircraft_gun_fire_control_radar_vehicle.glb';
  51. import centerModel from 'public/static/model/the_white_house.glb';
  52. import radarModel from 'public/static/model/radar.glb'
  53. import { mapGetters } from "vuex";
  54. import CesiumNavigation from 'cesium-navigation-es6/viewerCesiumNavigationMixin'
  55. export default {
  56. components: {
  57. TimeLine
  58. },
  59. computed: {
  60. ...mapGetters([
  61. "dimension"
  62. ])
  63. },
  64. data() {
  65. return {
  66. save: false,
  67. situation: [],
  68. nameIdList: [],
  69. websocket: null,
  70. leftwidth: 12,
  71. unit: [],
  72. satellite: [],
  73. center: [],
  74. move_data: {},
  75. _viewer2D: null,
  76. _viewer3D: null,
  77. mousevalue: null,
  78. // 选中的点
  79. selectedMarker: null,
  80. // 以前的标记点坐标
  81. oldPosition: null,
  82. activeName: 'fouth',
  83. currentLab: {
  84. index: -1,
  85. isActive: false
  86. },
  87. url: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
  88. isShow: false,
  89. handler3D: null,
  90. handler2D: null,
  91. image: null,
  92. modeltooltip: null,
  93. id: 1,
  94. showLayers: null,
  95. timeDataArray: ['Time 1', 'Time 2', 'Time 3', 'Time 4'],
  96. jsonData: null,
  97. mapNavOptions: {
  98. // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和Cesium.Rectangle.
  99. defaultResetView: this.Cesium.Cartographic.fromDegrees(110, 30, 2000000),
  100. // 罗盘
  101. enableCompass: true,
  102. // 缩放控件
  103. enableZoomControls: false,
  104. // 距离图例
  105. enableDistanceLegend: true,
  106. // 指南针外环
  107. enableCompassOuterRing: true
  108. }
  109. };
  110. },
  111. watch: {
  112. dimension: {
  113. handler: function (val, oldVal) {
  114. console.log(val)
  115. if (val == 2) {
  116. this.leftwidth = 24;
  117. } else if (val == 3) {
  118. this.leftwidth = 0;
  119. } else if (val == 5) {
  120. this.leftwidth = 12;
  121. }
  122. },
  123. },
  124. },
  125. activated() {
  126. this.getData();
  127. },
  128. mounted() {
  129. this.cesiumInit();
  130. // this.pointMove();
  131. // this.startWebSocket();
  132. },
  133. methods: {
  134. async getJson(row) {
  135. let redunit = [];
  136. let blueunit = [];
  137. let satellite = [];
  138. let center = [];
  139. let fileInfoStr = row.xdfile;
  140. let fileInfoArr = JSON.parse(fileInfoStr);
  141. await axios
  142. .get("http://127.0.0.1:8084/admin/online/onlineOperation/downloadDatasource/main", {
  143. params: {
  144. datasourceId: "1656243335922192384",
  145. fieldName: "xdfile",
  146. asImage: false,
  147. dataId: row.id,
  148. filename: fileInfoArr[0].filename,
  149. Authorization: getToken(),
  150. MenuId: "1656244747347431424"
  151. }
  152. })
  153. .then((response) => {
  154. console.log('response.data :>> ', response.data);
  155. // // 处理成功的响应
  156. // jsonData = response.data
  157. blueunit = response.data.blueunit
  158. redunit = response.data.redunit
  159. satellite = response.data.satellite
  160. center = response.data.center
  161. this.save = true
  162. this.jsonData = {
  163. id: row.id,
  164. xdname: response.data.xdname,
  165. type: response.data.type,
  166. // creator: row.creator,
  167. createtime: response.data.createtime,
  168. bluecnt: response.data.bluecnt,
  169. target: response.data.target,
  170. starttime: response.data.starttime,
  171. steptime: response.data.steptime,
  172. endtime: response.data.endtime,
  173. blueunit: blueunit,
  174. redunit: redunit,
  175. satellite: satellite,
  176. center: center
  177. }
  178. this.setTimeLine(response.data.starttime, response.data.endtime, response.data.steptime)//传入时间到时间轴
  179. })
  180. .catch((error) => {
  181. // 处理错误
  182. console.error(error);
  183. });
  184. for (let i = 0; i < blueunit.length; i++) {
  185. this.markLocationbyJson(parseFloat(blueunit[i].pos.lat), parseFloat(blueunit[i].pos.lon), parseFloat(blueunit[i].pos.height), blueunit[i].name, "blue")
  186. }
  187. for (let i = 0; i < center.length; i++) {
  188. let item = center[i]
  189. this.markLocationbyJson(parseFloat(item[center[i].name].properties.lat), parseFloat(item[center[i].name].properties.lon), parseFloat(item[center[i].name].properties.h), item.name, "center")
  190. }
  191. for (let i = 0; i < redunit.length; i++) {
  192. this.markLocationbyJson(parseFloat(redunit[i].component_movementjson.properties.launch_lat), parseFloat(redunit[i].component_movementjson.properties.launch_lon), parseFloat(redunit[i].component_movementjson.properties.launch_h), redunit[i].name, "red")
  193. let point1 = {
  194. longitude: parseFloat(redunit[i].component_movementjson.properties.launch_lon),
  195. latitude: parseFloat(redunit[i].component_movementjson.properties.launch_lat),
  196. height: parseFloat(redunit[i].component_movementjson.properties.launch_h)
  197. }
  198. let point2 = {
  199. longitude: parseFloat(redunit[i].component_movementjson.properties.target_lon),
  200. latitude: parseFloat(redunit[i].component_movementjson.properties.target_lat),
  201. height: parseFloat(redunit[i].component_movementjson.properties.target_h)
  202. }
  203. this.markLine(point1, point2, "red")
  204. }
  205. },
  206. //获取所有数据
  207. getData() {
  208. this.getCenter();
  209. this.getSatellite();
  210. this.getUnit();
  211. this.getSituation();
  212. },
  213. // 获取场景想定数据
  214. getSituation() {
  215. let params = {
  216. datasourceId: "1656243335922192384",
  217. filterDtoList: [],
  218. pageParam: {
  219. pageNum: 1,
  220. pageSize: 10
  221. }
  222. };
  223. fireController.situation(this, params).then((res) => {
  224. this.situation = res.data.dataList;
  225. });
  226. },
  227. // 获取作战单元数据
  228. getUnit() {
  229. let params = {
  230. datasourceId: "1657931215497334784",
  231. filterDtoList: [],
  232. pageParam: {
  233. pageNum: 1,
  234. pageSize: 10
  235. }
  236. };
  237. fireController.unit(this, params).then((res) => {
  238. this.unit = res.data.dataList;
  239. });
  240. },
  241. // 获取指挥中心数据
  242. getCenter() {
  243. let params = {
  244. datasourceId: "1654421731512684544",
  245. filterDtoList: [],
  246. pageParam: {
  247. pageNum: 1,
  248. pageSize: 10
  249. }
  250. };
  251. fireController.center(this, params).then((res) => {
  252. this.center = res.data.dataList;
  253. });
  254. },
  255. // 获取预警卫星数据
  256. getSatellite() {
  257. let params = {
  258. datasourceId: "1654424480958648320",
  259. filterDtoList: [],
  260. pageParam: {
  261. pageNum: 1,
  262. pageSize: 10
  263. }
  264. };
  265. fireController.satellite(this, params).then((res) => {
  266. this.satellite = res.data.dataList;
  267. });
  268. },
  269. cesiumInit() {
  270. this.$data._viewer2D = new this.Cesium.Viewer("2DcesiumContainer", {
  271. sceneMode: this.Cesium.SceneMode.SCENE2D,
  272. animation: true, // 是否显示时间轴动画
  273. baseLayerPicker: false,
  274. homeButton: false,
  275. geocoder: false,
  276. timeline: true, //是否显示时间线控件
  277. fullscreenButton: false,
  278. sceneModePicker: false,
  279. navigationHelpButton: false,
  280. selectionIndicator: false,
  281. imageryProvider: new this.Cesium.UrlTemplateImageryProvider({
  282. url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
  283. layer: "tdtVecBasicLayer",
  284. style: "default",
  285. format: "image/png",
  286. tileMatrixSetID: "GoogleMapsCompatible",
  287. show: false
  288. })
  289. });
  290. this.$data._viewer3D = new this.Cesium.Viewer("3DcesiumContainer", {
  291. animation: true, // 是否显示时间轴动画
  292. baseLayerPicker: false,
  293. homeButton: false,
  294. geocoder: false,
  295. timeline: true, //是否显示时间线控件
  296. fullscreenButton: false,
  297. sceneModePicker: false,
  298. navigationHelpButton: false,
  299. selectionIndicator: false,
  300. // imageryProvider: new this.Cesium.WebMapServiceImageryProvider({
  301. // url: '/geoserver/map/wms',
  302. // // 这里是自定义的图层名称
  303. // layers: 'map',
  304. // parameters: {
  305. // service: 'WMS',
  306. // format: 'image/png',
  307. // transparent: true
  308. // }
  309. // }),
  310. imageryProvider:
  311. // new this.Cesium.WebMapTileServiceImageryProvider({
  312. // url: "http://10.170.16.95:8080/geoserver/gwc/service/wmts/rest/map:map/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png",
  313. // layer: 'map:map',
  314. // style: 'raster',
  315. // format: 'image/png',
  316. // tileMatrixSetID: 'EPSG:900913', //一般使用EPSG:3857坐标系
  317. // }),
  318. new this.Cesium.UrlTemplateImageryProvider({
  319. url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
  320. layer: "tdtVecBasicLayer",
  321. style: "default",
  322. format: "image/png",
  323. tileMatrixSetID: "GoogleMapsCompatible",
  324. show: false
  325. })
  326. });
  327. this.$data._viewer3D._cesiumWidget._creditContainer.style.display = "none";
  328. this.$data._viewer2D._cesiumWidget._creditContainer.style.display = "none";
  329. this.$data._viewer3D.camera.setView({
  330. destination: new this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000)
  331. // 方向,俯视和仰视的视角
  332. // orientation:{
  333. // heading: this.Cesium.Math.toRadians(90),//坐标系旋转90度
  334. // pitch: this.Cesium.Math.toRadians(-45) ,//设置俯仰角度为-45度
  335. // }
  336. });
  337. this.$data._viewer2D.camera.setView({
  338. destination: new this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000)
  339. // 方向,俯视和仰视的视角
  340. // orientation:{
  341. // heading: this.Cesium.Math.toRadians(90),//坐标系旋转90度
  342. // pitch: this.Cesium.Math.toRadians(-45) ,//设置俯仰角度为-45度
  343. // }
  344. });
  345. // this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 1500000; //相机高度的最大值
  346. this.$data._viewer2D.camera.percentageChanged = 0.01;
  347. this.$data._viewer2D.camera.changed.addEventListener(this.sync); //地图移动事件
  348. this.$data._viewer3D.camera.percentageChanged = 0.01;
  349. this.$data._viewer3D.camera.changed.addEventListener(this.sync); //地图移动事件
  350. this.$data._viewer2D.camera.moveEnd.addEventListener(this.getCammeraHeightAndZoom) //地图缩放事件
  351. this.$data._viewer3D.camera.moveEnd.addEventListener(this.getCammeraHeightAndZoom) //地图缩放事件
  352. this.handler2D = new this.Cesium.ScreenSpaceEventHandler(this.$data._viewer2D.scene.canvas);
  353. this.handler3D = new this.Cesium.ScreenSpaceEventHandler(this.$data._viewer3D.scene.canvas);
  354. //设置导航组件
  355. new CesiumNavigation(this.$data._viewer2D, this.mapNavOptions);
  356. new CesiumNavigation(this.$data._viewer3D, this.mapNavOptions);
  357. },
  358. sync() {
  359. if (this.mousevalue == "3D") {
  360. // 三维地图中心点
  361. let center = new this.Cesium.Cartesian2(
  362. Math.floor(this.$data._viewer3D.canvas.clientWidth / 2),
  363. Math.floor(this.$data._viewer3D.canvas.clientHeight / 2)
  364. );
  365. // 转为世界坐标系
  366. let position = this.$data._viewer3D.scene.camera.pickEllipsoid(center);
  367. // 判断中心点是否在椭球体上
  368. if (this.Cesium.defined(position)) {
  369. // 获取三维地图中心点与相机之间的距离
  370. let distance = this.Cesium.Cartesian3.distance(position, this.$data._viewer3D.scene.camera.positionWC);
  371. position = this.convertWorldToCartographic(position);
  372. // 更新二维地图
  373. this.$data._viewer2D.scene.camera.setView({
  374. destination: new this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, distance)
  375. });
  376. }
  377. }
  378. if (this.mousevalue == "2D") {
  379. // 二维地图中心点
  380. let center = new this.Cesium.Cartesian2(
  381. Math.floor(this.$data._viewer2D.canvas.clientWidth / 2),
  382. Math.floor(this.$data._viewer2D.canvas.clientHeight / 2)
  383. );
  384. // 转为世界坐标系
  385. let position = this.$data._viewer2D.scene.camera.pickEllipsoid(center);
  386. // 判断中心点是否在椭球体上
  387. if (this.Cesium.defined(position)) {
  388. // 获取三维地图中心点与相机之间的距离
  389. let distance = this.$data._viewer2D.scene.camera.positionCartographic.height;
  390. position = this.convertWorldToCartographic(position);
  391. // 更新三维地图
  392. this.$data._viewer3D.scene.camera.setView({
  393. destination: new this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, distance)
  394. });
  395. }
  396. }
  397. },
  398. // 将世界坐标系转换为经纬度坐标系
  399. convertWorldToCartographic(worldPosition) {
  400. const ellipsoid = this.$data._viewer2D.scene.globe.ellipsoid;
  401. const cartographic = ellipsoid.cartesianToCartographic(worldPosition);
  402. const longitude = this.Cesium.Math.toDegrees(cartographic.longitude);
  403. const latitude = this.Cesium.Math.toDegrees(cartographic.latitude);
  404. const height = cartographic.height;
  405. return { longitude, latitude, height };
  406. },
  407. // 监听地图变化
  408. changeActive(value) {
  409. this.mousevalue = value;
  410. },
  411. dimensionswitch(value) {
  412. this.dimension = value;
  413. this.selectModel();
  414. },
  415. // 全屏缩小
  416. ismax() {
  417. if (screenfull.isEnabled && screenfull.isFullscreen) {
  418. screenfull.exit();
  419. } else {
  420. screenfull.request();
  421. }
  422. },
  423. /* 获取camera中心点坐标 */
  424. getCenterPosition(is3D = false) {
  425. let viewer = is3D ? this.$data._viewer3D : this.$data._viewer2D;
  426. let result = viewer.camera.pickEllipsoid(
  427. new this.Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2)
  428. );
  429. let curPosition = this.Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
  430. let lon = (curPosition.longitude * 180) / Math.PI;
  431. let lat = (curPosition.latitude * 180) / Math.PI;
  432. let height = viewer.camera.positionCartographic.height;
  433. return {
  434. lon: lon,
  435. lat: lat,
  436. height: height
  437. };
  438. },
  439. /* 地图放大 */
  440. big() {
  441. let { lon, lat, height } = this.getCenterPosition(this.dimension === 3);
  442. let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
  443. // 镜头拉进
  444. viewer.camera.flyTo({
  445. destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, height / 1.8),
  446. duration: 1.0
  447. });
  448. },
  449. /* 地图缩小 */
  450. small() {
  451. let { lon, lat, height } = this.getCenterPosition(this.dimension === 3);
  452. let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
  453. // 镜头远离
  454. viewer.camera.flyTo({
  455. destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, height * 1.2),
  456. duration: 1.0
  457. });
  458. },
  459. home() {
  460. let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
  461. viewer.camera.flyTo({
  462. destination: this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000),
  463. duration: 2.0
  464. });
  465. },
  466. // tabs 切换点击
  467. legendClick({ index }) {
  468. this.selectModel();
  469. let tab_content = document.querySelectorAll(".menu .el-tabs__content");
  470. if (this.currentLab.index == index) {
  471. tab_content[0].style.display == "none" || ""
  472. ? (tab_content[0].style.display = "block")
  473. : (tab_content[0].style.display = "none");
  474. }
  475. if (this.currentLab.index != index) {
  476. this.currentLab.index = index;
  477. tab_content[0].style.display = "block";
  478. }
  479. },
  480. mouseMove(event) {
  481. if (this.$refs.modeltooltip) {
  482. this.$refs.modeltooltip.style.left = event.pageX - 240 + "px";
  483. this.$refs.modeltooltip.style.top = event.pageY - 115 + "px";
  484. }
  485. },
  486. //显示鼠标经纬度
  487. getMouseLocation(event) {
  488. let { longitude, latitude } = this.getCoordinatesFromEvent(event);
  489. this.$store.commit("app/setMouseLocation", { longitude, latitude });
  490. },
  491. /*根据camera高度近似计算当前层级*/
  492. heightToZoom(height) {
  493. var A = 40487.57;
  494. var B = 0.00007096758;
  495. var C = 91610.74;
  496. var D = -40467.74;
  497. return Math.round(D + (A - D) / (1 + Math.pow(height / C, B)));
  498. },
  499. getCammeraHeightAndZoom() {
  500. let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
  501. //获取当前相机高度
  502. let height = viewer.camera.positionCartographic.height;
  503. let zoom = this.heightToZoom(height);
  504. this.$store.commit("app/setCameraHeightAndZoom", { height, zoom });
  505. },
  506. selectModel(cursorStyle, image, info) {
  507. console.log('image :>> ', image);
  508. let earthMap = document.getElementById("earth");
  509. earthMap.style.cursor = cursorStyle || "auto";
  510. if (cursorStyle) {
  511. document.addEventListener("mousemove", this.mouseMove);
  512. this.isShow = true;
  513. this.image = image;
  514. this.modeltooltip = info;
  515. } else {
  516. document.removeEventListener("mousemove", this.mouseMove);
  517. this.isShow = false;
  518. this.image = null;
  519. this.modeltooltip = null;
  520. }
  521. },
  522. markLocationbyJson(latitude, longitude, height, name, type) {
  523. const position = this.Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
  524. console.log('position :>> ', position);
  525. let color = ''
  526. let modelUrl = ''
  527. if (type == 'red') {
  528. color = 'Red'
  529. modelUrl = missileModel
  530. }
  531. else if (type == 'blue') {
  532. color = 'Blue'
  533. modelUrl = radarModel
  534. }
  535. else if (type == 'center') {
  536. color = 'Blue'
  537. modelUrl = centerModel
  538. }
  539. else if (type == 'satelite') {
  540. color = 'Blue'
  541. modelUrl = satelliteModel
  542. }
  543. this.$data._viewer2D.entities.add({
  544. id: this.id,
  545. position: position,
  546. point: {
  547. pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  548. color: this.Cesium.Color.fromCssColorString(color)
  549. },
  550. model: {
  551. uri: modelUrl, // 替换为你的3D模型文件路径
  552. scale: 1.0, // 调整3D模型的缩放大小
  553. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  554. },
  555. label: {
  556. text: type + ' ' + name,
  557. show: true,
  558. font: "18px Helvetica", // 调整标签的字体样式和大小
  559. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  560. }
  561. });
  562. this.$data._viewer3D.entities.add({
  563. id: this.id,
  564. position: position,
  565. point: {
  566. pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  567. color: this.Cesium.Color.fromCssColorString(color)
  568. },
  569. model: {
  570. uri: modelUrl, // 替换为你的3D模型文件路径
  571. scale: 1.0, // 调整3D模型的缩放大小
  572. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  573. },
  574. label: {
  575. text: type + ' ' + name,
  576. show: true,
  577. font: "18px Helvetica", // 调整标签的字体样式和大小
  578. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  579. }
  580. });
  581. this.nameIdList.push({
  582. id: this.id,
  583. name: name
  584. })
  585. this.id++;
  586. },
  587. // 从鼠标点击事件获取坐标
  588. getCoordinatesFromEvent(event) {
  589. let viewer = this.mousevalue === "2D" ? this.$data._viewer2D : this.$data._viewer3D;
  590. let clickPosition;
  591. if (this.dimension === 5 && this.mousevalue === "3D") {
  592. clickPosition = new this.Cesium.Cartesian2(event.clientX - 1080, event.clientY - 160);
  593. } else {
  594. clickPosition = new this.Cesium.Cartesian2(event.clientX - 280, event.clientY - 160);
  595. }
  596. // 获取地图上的经纬度
  597. const viewerPosition = viewer.scene.camera.pickEllipsoid(clickPosition);
  598. const cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(viewerPosition);
  599. const latitude = this.Cesium.Math.toDegrees(cartographic.latitude);
  600. const longitude = this.Cesium.Math.toDegrees(cartographic.longitude);
  601. return {
  602. latitude,
  603. longitude
  604. };
  605. },
  606. markLine(point1, point2, color) {
  607. // 从点1和点2的WGS84坐标创建Cartesian3对象
  608. const position1 = this.Cesium.Cartesian3.fromDegrees(point1.longitude, point1.latitude, point1.height || 0);
  609. const position2 = this.Cesium.Cartesian3.fromDegrees(point2.longitude, point2.latitude, point2.height || 0);
  610. // 创建一个带有箭头图标的PolylineMaterial
  611. const material = new this.Cesium.PolylineArrowMaterialProperty(
  612. this.Cesium.Color.fromCssColorString(color || "red")
  613. );
  614. // 将点1和点2之间的连线添加到Viewer中
  615. this.$data._viewer2D.entities.add({
  616. polyline: {
  617. positions: [position1, position2],
  618. width: 5, // 设置线的宽度
  619. material: material,
  620. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  621. }
  622. });
  623. this.$data._viewer3D.entities.add({
  624. polyline: {
  625. positions: [position1, position2],
  626. width: 5, // 设置线的宽度
  627. material: material,
  628. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  629. }
  630. });
  631. },
  632. markSatelliteLine(position1, position2, color,viewer) {
  633. // 创建一个带有箭头图标的PolylineMaterial
  634. const material = new this.Cesium.PolylineArrowMaterialProperty(
  635. this.Cesium.Color.fromCssColorString(color || "red")
  636. );
  637. // 将点1和点2之间的连线添加到Viewer中
  638. viewer.entities.add({
  639. polyline: {
  640. positions: [position1, position2],
  641. width: 5, // 设置线的宽度
  642. material: material,
  643. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  644. }
  645. });
  646. },
  647. setTimeLine(startTime, endtime, stepTime) {
  648. let start = this.Cesium.JulianDate.fromDate(new Date(startTime)); // 设置时间轴当前时间为开始时间
  649. let stop = this.Cesium.JulianDate.fromDate(new Date(endtime));
  650. // 添加8小时,使地图时间和北京时间相同
  651. start = this.Cesium.JulianDate.addHours(start, 8, new this.Cesium.JulianDate());
  652. stop = this.Cesium.JulianDate.addHours(stop, 8, new this.Cesium.JulianDate());
  653. // 设置时钟开始时间
  654. this.$data._viewer2D.clock.startTime = start.clone();
  655. this.$data._viewer3D.clock.startTime = start.clone();
  656. // 设置时钟当前时间
  657. this.$data._viewer2D.clock.currentTime = start.clone();
  658. this.$data._viewer3D.clock.currentTime = start.clone();
  659. // 设置时钟结束时间
  660. this.$data._viewer2D.clock.stopTime = stop.clone();
  661. this.$data._viewer3D.clock.stopTime = stop.clone();
  662. // 时间速率,数字越大时间过的越快,设置1好像是和实际时间一样
  663. this.$data._viewer2D.clock.multiplier = stepTime;
  664. this.$data._viewer3D.clock.multiplier = stepTime;
  665. // 时间轴绑定到viewer上去
  666. this.$data._viewer2D.timeline.zoomTo(start, stop);
  667. this.$data._viewer3D.timeline.zoomTo(start, stop);
  668. // 循环执行,到达终止时间,重新从起点时间开始
  669. this.$data._viewer2D.clock.clockRange = this.Cesium.ClockRange.LOOP_STOP;
  670. this.$data._viewer3D.clock.clockRange = this.Cesium.ClockRange.LOOP_STOP;
  671. this.$data._viewer2D.clock.onTick.addEventListener(clock => {
  672. const currentTime = clock.currentTime; // 获取当前时间轴的时间
  673. const elapsedTime = this.Cesium.JulianDate.secondsDifference(
  674. currentTime,
  675. this.$data._viewer2D.clock.startTime
  676. ); // 获取从起始时间到当前时间的秒数
  677. if (parseInt(elapsedTime) % stepTime === 0 && elapsedTime != 0) {
  678. console.log('elapsedTime :>> ', elapsedTime);
  679. // 当从起始时间到当前时间的秒数是 stepTime 的倍数时,发送请求
  680. this.requestDataAndUpdateModel2D(startTime, elapsedTime);
  681. }
  682. });
  683. this.$data._viewer3D.clock.onTick.addEventListener(clock => {
  684. const currentTime = clock.currentTime; // 获取当前时间轴的时间
  685. const elapsedTime = this.Cesium.JulianDate.secondsDifference(
  686. currentTime,
  687. this.$data._viewer3D.clock.startTime
  688. ); // 获取从起始时间到当前时间的秒数
  689. if (parseInt(elapsedTime) % stepTime === 0 && elapsedTime != 0) {
  690. console.log('elapsedTime :>> ', elapsedTime);
  691. // 当从起始时间到当前时间的秒数是 stepTime 的倍数时,发送请求
  692. this.requestDataAndUpdateModel3D(startTime, elapsedTime);
  693. }
  694. });
  695. this.initSTK()
  696. },
  697. // 初始化stk方法,生成轨迹文件
  698. async initSTK() {
  699. console.log('this.jsonData :>> ', this.jsonData);
  700. // await axios
  701. // .get("/api", this.jsonData).then(res=>{
  702. // console.log('res :>> ', res);
  703. // })
  704. const config = {
  705. timeout: 0 // 设置超时时间为0,表示忽略超时问题
  706. };
  707. await axios
  708. .post("/api/traj", this.jsonData,config).then(res => {
  709. console.log('res :>> ', res);
  710. let data = res.data[1].data[0]
  711. for (let key in data) {
  712. let isSatellite = true
  713. //判断是否为卫星
  714. for (let i = 0; i < this.nameIdList.length; i++) {
  715. if (key === this.nameIdList[i].name || key === 'dateTime') {
  716. isSatellite = false
  717. break
  718. }
  719. }
  720. // 新建卫星实体
  721. if (isSatellite) {
  722. console.log('key :>> ', key);
  723. let x = parseFloat(data[key].x) * 1000
  724. let y = parseFloat(data[key].y) * 1000
  725. let z = parseFloat(data[key].z) * 1000
  726. //终点位置
  727. let position = new this.Cesium.Cartesian3(x, y, z);
  728. this.$data._viewer2D.entities.add({
  729. id: this.id,
  730. position: position,
  731. point: {
  732. pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  733. color: this.Cesium.Color.fromCssColorString('Blue')
  734. },
  735. model: {
  736. uri: satelliteModel, // 替换为你的3D模型文件路径
  737. scale: 1.0, // 调整3D模型的缩放大小
  738. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  739. },
  740. label: {
  741. text: 'satellite ' + key,
  742. show: true,
  743. font: "18px Helvetica", // 调整标签的字体样式和大小
  744. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  745. }
  746. });
  747. this.$data._viewer3D.entities.add({
  748. id: this.id,
  749. position: position,
  750. point: {
  751. pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  752. color: this.Cesium.Color.fromCssColorString('Blue')
  753. },
  754. model: {
  755. uri: satelliteModel, // 替换为你的3D模型文件路径
  756. scale: 1.0, // 调整3D模型的缩放大小
  757. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  758. },
  759. label: {
  760. text: 'satellite ' + key,
  761. show: true,
  762. font: "18px Helvetica", // 调整标签的字体样式和大小
  763. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  764. }
  765. });
  766. this.nameIdList.push({
  767. id: this.id,
  768. name: key
  769. })
  770. this.id++;
  771. }
  772. }
  773. })
  774. },
  775. // 根据时间参数请求模型位置并更新 2D
  776. async requestDataAndUpdateModel2D(startTime, elapsedTime) {
  777. const jsDate = new Date(startTime);
  778. // 增加 elapsedTime 秒
  779. jsDate.setSeconds(jsDate.getSeconds() + elapsedTime);
  780. // 转换为需求字符串格式
  781. const newTimeString = `${jsDate.getFullYear()}-${(jsDate.getMonth() + 1).toString().padStart(2, '0')}-${jsDate.getDate().toString().padStart(2, '0')} ${jsDate.getHours().toString().padStart(2, '0')}:${jsDate.getMinutes().toString().padStart(2, '0')}:${jsDate.getSeconds().toString().padStart(2, '0')}`;
  782. await axios
  783. .post("/api/pos", { simulation_time: newTimeString + '.000' }).then(res => {
  784. console.log('res :>> ', res);
  785. let data = res.data[1].data
  786. //依次更新每个模型位置
  787. for (let i = 0; i < this.nameIdList.length; i++) {
  788. if (data[this.nameIdList[i].name] != null && data[this.nameIdList[i].name] != undefined) {
  789. this.modelEntityMoveByIDAndLocation(this.$data._viewer2D, this.nameIdList[i].id, data[this.nameIdList[i].name].x, data[this.nameIdList[i].name].y, data[this.nameIdList[i].name].z)
  790. }
  791. }
  792. //更新模型位置
  793. // this.modelEntityMoveByIDAndLocation(this.$data._viewer2D,"1654426964397658112",res.data[1].data.W1.x,res.data[1].data.W1.y,res.data[1].data.W1.z)
  794. })
  795. },
  796. // 根据时间参数请求模型位置并更新 3D
  797. async requestDataAndUpdateModel3D(startTime, elapsedTime) {
  798. const jsDate = new Date(startTime);
  799. // 增加 elapsedTime 秒
  800. jsDate.setSeconds(jsDate.getSeconds() + elapsedTime);
  801. // 转换为需求字符串格式
  802. const newTimeString = `${jsDate.getFullYear()}-${(jsDate.getMonth() + 1).toString().padStart(2, '0')}-${jsDate.getDate().toString().padStart(2, '0')} ${jsDate.getHours().toString().padStart(2, '0')}:${jsDate.getMinutes().toString().padStart(2, '0')}:${jsDate.getSeconds().toString().padStart(2, '0')}`;
  803. await axios
  804. .post("/api/pos", { simulation_time: newTimeString + '.000' }).then(res => {
  805. let data = res.data[1].data
  806. //依次更新每个模型位置
  807. for (let i = 0; i < this.nameIdList.length; i++) {
  808. if (this.nameIdList[i].name in data) {
  809. console.log(' 开始移动' + this.nameIdList[i].name);
  810. this.modelEntityMoveByIDAndLocation(this.$data._viewer3D, this.nameIdList[i].id, data[this.nameIdList[i].name].x, data[this.nameIdList[i].name].y, data[this.nameIdList[i].name].z)
  811. }
  812. }
  813. //更新模型位置
  814. // this.modelEntityMoveByIDAndLocation(this.$data._viewer3D,viewer,"1654426964397658112",res.data[1].data.W1.x,res.data[1].data.W1.y,res.data[1].data.W1.z)
  815. })
  816. },
  817. // 根据模型实体Id和终点位置进行移动
  818. modelEntityMoveByIDAndLocation(viewer, id, x, y, z) {
  819. x = parseFloat(x) * 1000
  820. y = parseFloat(y) * 1000
  821. z = parseFloat(z) * 1000
  822. let entity = viewer.entities.getById(id)
  823. //终点位置
  824. let position = new this.Cesium.Cartesian3(x, y, z);
  825. let oldPosition = viewer.entities.getById(id).position._value
  826. //设置方向,根据实体的位置来配置方向
  827. entity.orientation = new this.Cesium.VelocityOrientationProperty(entity.position);
  828. //设置实体位置
  829. entity.position.setValue(position)
  830. this.markSatelliteLine(oldPosition,position,'Blue',viewer)
  831. }
  832. }
  833. };
  834. </script>
  835. <style scoped>
  836. ::v-deep .cesium-infoBox {
  837. display: none !important;
  838. }
  839. ::v-deep .cesium-infoBox-bodyless {
  840. display: none !important;
  841. }
  842. ::v-deep .cesium-infoBox-visible {
  843. display: none !important;
  844. }
  845. .container {
  846. height: 100%;
  847. position: relative;
  848. }
  849. .modeltooltip {
  850. position: absolute;
  851. padding: 5px;
  852. color: #fff;
  853. font-size: 20px;
  854. pointer-events: none;
  855. z-index: 999;
  856. }
  857. .myHeader {
  858. background-color: #1c222b !important;
  859. color: #fff;
  860. height: 100%;
  861. display: flex;
  862. flex-direction: row;
  863. align-items: center;
  864. /*由于flex-direction: column,因此align-items代表的是水平方向*/
  865. justify-content: center;
  866. /*由于flex-direction: column,因此justify-content代表的是垂直方向*/
  867. }
  868. .myHeader .el-button {
  869. width: 100px;
  870. height: 20px;
  871. padding: 1px 23px;
  872. }
  873. .box-card {
  874. min-height: 100%;
  875. height: 100%;
  876. }
  877. ::v-deep .el-card__body {
  878. height: 100% !important;
  879. padding: 0px !important;
  880. }
  881. .main-layout {
  882. height: 100%;
  883. width: 100%;
  884. }
  885. .map {
  886. width: 100%;
  887. height: 100%;
  888. }
  889. .menu {
  890. position: absolute;
  891. height: 400px;
  892. z-index: 999;
  893. left: 20px;
  894. top: 20px;
  895. }
  896. ::v-deep .el-tabs--left .el-tabs__header.is-left {
  897. margin-right: 0px !important;
  898. }
  899. .buttons {
  900. display: flex;
  901. flex-direction: column;
  902. align-items: center;
  903. justify-items: center;
  904. position: absolute;
  905. z-index: 999;
  906. right: 20px;
  907. top: 20px;
  908. }
  909. .el-button {
  910. margin: 5px !important;
  911. }
  912. ::v-deep .el-tabs--border-card>.el-tabs__content {
  913. width: 300px;
  914. height: 100%;
  915. overflow-y: visible;
  916. }
  917. .model {
  918. display: flex;
  919. width: 100%;
  920. flex-wrap: wrap;
  921. }
  922. .model>div {
  923. width: 50%;
  924. height: 120px;
  925. padding: 5px;
  926. }
  927. .model>div:hover {
  928. border: 2px solid blue;
  929. }
  930. .model>div:active {
  931. border: 2px solid red;
  932. }
  933. .active {
  934. border: 2px solid red !important;
  935. }
  936. .model .el-image {
  937. display: block !important;
  938. }
  939. ::v-deep .el-image .el-image__inner {
  940. border: 1px solid #ddd;
  941. border-radius: 5px;
  942. }
  943. .item {
  944. font-size: 14px;
  945. /* right: 20px; */
  946. }
  947. .TimeLine {
  948. position: absolute;
  949. left: 21%;
  950. bottom: 15px;
  951. transform: translateX(-50%);
  952. }
  953. /* 罗盘样式 */
  954. /deep/.compass {
  955. pointer-events: auto;
  956. position: absolute;
  957. right: 0px;
  958. top: 280px;
  959. width: 95px;
  960. height: 95px;
  961. overflow: hidden;
  962. }
  963. </style>