index.vue 30 KB

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