MainMap.vue 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. <template>
  2. <div class="viewer_container">
  3. <div id="cesiumContainer">
  4. <!-- <div class="get_now_camera_view">
  5. <van-button @click="consoleCameraPosition"> 当前视角 </van-button>
  6. <van-button @click="setViewDefaultlocation"> 复位 </van-button>
  7. </div>
  8. <van-popup
  9. v-model:show="dialogVisible"
  10. :style="{ height: '50%', width: '80%' }"
  11. :closed="hideInfoDailog"
  12. >
  13. <div>
  14. <div style="font-size: 16px">{{ dialogInfoStr }}</div>
  15. <van-button @click="hideInfoDailog">关 闭</van-button>
  16. <van-button :class="'copy_info_dialog'" type="primary">
  17. 复 制
  18. </van-button>
  19. </div>
  20. </van-popup> -->
  21. </div>
  22. <Tool></Tool>
  23. </div>
  24. </template>
  25. <script>
  26. // import Clipboard from "clipboard";
  27. import { defineAsyncComponent } from "vue";
  28. import Water from "@/utils/Water";
  29. import api from "@/api/content";
  30. export default {
  31. data() {
  32. return {
  33. dialogVisible: false,
  34. dialogInfoStr: "",
  35. clipboard: null,
  36. correctCamera: false,
  37. waterObj: null, // 水面实例
  38. flylineObj: [], // 飞线数组
  39. topK: [
  40. {
  41. lon: 121.12265818599361,
  42. lat: 31.153907327111906,
  43. h: 12.178229477117695,
  44. },
  45. {
  46. lon: 121.12264787421734,
  47. lat: 31.15395149031556,
  48. h: 12.178192986180326,
  49. },
  50. {
  51. lon: 121.12278546708409,
  52. lat: 31.153975342725264,
  53. h: 12.178415363887282,
  54. },
  55. {
  56. lon: 121.12281310059657,
  57. lat: 31.15385762853425,
  58. h: 12.178399877503464,
  59. },
  60. {
  61. lon: 121.1228576094918,
  62. lat: 31.15386519051712,
  63. h: 12.178394232107442,
  64. },
  65. {
  66. lon: 121.1228909000206,
  67. lat: 31.153723309251856,
  68. h: 12.17857353611858,
  69. },
  70. {
  71. lon: 121.12294578609598,
  72. lat: 31.153732796983615,
  73. h: 12.178675754028028,
  74. },
  75. {
  76. lon: 121.12298033312791,
  77. lat: 31.153585333373417,
  78. h: 12.17876227737616,
  79. },
  80. {
  81. lon: 121.1228480316718,
  82. lat: 31.15356239349922,
  83. h: 12.178326652099466,
  84. },
  85. {
  86. lon: 121.12283863696666,
  87. lat: 31.153602052352188,
  88. h: 12.178301731797035,
  89. },
  90. {
  91. lon: 121.12279132401528,
  92. lat: 31.153593731079162,
  93. h: 12.17821160134978,
  94. },
  95. {
  96. lon: 121.12280904366847,
  97. lat: 31.153517944755357,
  98. h: 12.178387628978598,
  99. },
  100. {
  101. lon: 121.12256003807408,
  102. lat: 31.15347475524662,
  103. h: 12.178108003497535,
  104. },
  105. {
  106. lon: 121.12255140331416,
  107. lat: 31.153510889388823,
  108. h: 12.178086221333002,
  109. },
  110. {
  111. lon: 121.12251427275822,
  112. lat: 31.153504509859477,
  113. h: 12.17756730102783,
  114. },
  115. { lon: 121.1224291079002, lat: 31.15386748647, h: 12.177529555001517 },
  116. ],
  117. };
  118. },
  119. components: {
  120. Tool: defineAsyncComponent(() => import("@/components/Tool.vue")),
  121. },
  122. created() { },
  123. mounted() {
  124. let that = this;
  125. // this.clipboard = new Clipboard(".copy_info_dialog", {
  126. // // 点击copy按钮,直接通过text直接返回复印的内容
  127. // text: function () {
  128. // return that.dialogInfoStr;
  129. // },
  130. // });
  131. this.waterObj = new Water();
  132. window.controlCZ = this.controlCZ;
  133. this.$root.$.appContext.config.globalProperties.$flyTo = this.flyTo;
  134. this.initViewer().then(() => {
  135. this.mapConfig();
  136. // 默认视角
  137. this.setViewDefaultlocation().then(() => {
  138. that.mainFunc();
  139. });
  140. });
  141. window.getNowCameraPosition1 = this.getNowCameraPosition;
  142. window.getNowCameraPosition = function () {
  143. this.getNowCameraPosition().then((result) => {
  144. this.showInfoDailog(result.info);
  145. });
  146. };
  147. return;
  148. },
  149. methods: {
  150. consoleCameraPosition() {
  151. this.getNowCameraPosition().then((result) => {
  152. this.showInfoDailog(
  153. JSON.stringify(result.result).replaceAll("{", "").replaceAll("}", "")
  154. );
  155. });
  156. },
  157. initViewer() {
  158. return new Promise((resolve, reject) => {
  159. globalVariable.viewer = new Cesium.Viewer("cesiumContainer", {
  160. animation: false, // 是否创建动画小器件,左下角仪表
  161. baseLayerPicker: false, // 是否显示图层选择器
  162. fullscreenButton: false, // 是否显示全屏按钮
  163. vrButton: false, // 是否创建VRButton小工具
  164. geocoder: false, // 是否显示geocoder小器件,右上角查询按钮
  165. homeButton: false, // 是否显示Home按钮
  166. infoBox: false, // 是否显示信息框
  167. sceneModePicker: false, // 是否显示3D/2D选择器
  168. selectionIndicator: false, // 是否显示选取指示器组件
  169. timeline: false, // 是否显示时间轴
  170. navigationHelpButton: false, // 是否显示右上角的帮助按钮
  171. navigationInstructionsInitiallyVisible: false, // 如果导航指示最初应可见,则为True;如果用户明确单击按钮后才显示,则为false。
  172. scene3DOnly: true, // 如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
  173. shouldAnimate: false, // 默认情况下,如果时钟应尝试提前模拟时间,则为true,否则为false。此选项优先于设置
  174. clock: new Cesium.Clock(), // 用于控制当前时间的时钟对象
  175. clockViewModel: new Cesium.ClockViewModel(
  176. new Cesium.Clock({
  177. startTime: Cesium.JulianDate.fromIso8601("2023-03-14T22:30:14Z"),
  178. currentTime: Cesium.JulianDate.fromIso8601(
  179. "2023-03-14T22:31:14Z"
  180. ),
  181. stopTime: Cesium.JulianDate.fromIso8601("2023-03-15T10:19:14Z"),
  182. clockRange: Cesium.ClockRange.LOOP_STOP,
  183. clockStep: Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER,
  184. })
  185. ), // 用于控制当前时间的时钟对象
  186. selectedImageryProviderViewModel: undefined, // 当前图像图层的显示模型,仅baseLayerPicker设为true有意义
  187. imageryProviderViewModels:
  188. Cesium.createDefaultImageryProviderViewModels(), // 可供BaseLayerPicker选择的图像图层ProviderViewModel数组
  189. selectedTerrainProviderViewModel: undefined, // 当前地形图层的显示模型,仅baseLayerPicker设为true有意义
  190. terrainProviderViewModels:
  191. Cesium.createDefaultTerrainProviderViewModels(), // 可供BaseLayerPicker选择的地形图层ProviderViewModel数组
  192. imageryProvider: new Cesium.SingleTileImageryProvider({
  193. url: (function createColorCanvas(color) {
  194. // 返回空白
  195. var width = 1,
  196. height = 1;
  197. var canvas = document.createElement("canvas");
  198. canvas.width = width;
  199. canvas.height = height;
  200. var ctx = canvas.getContext("2d");
  201. ctx.fillStyle = color;
  202. ctx.fillRect(0, 0, width, height);
  203. return canvas.toDataURL();
  204. })("#ffffff00"),
  205. rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
  206. }), // 图像图层提供者,仅baseLayerPicker设为false有意义
  207. fullscreenElement: document.body, // 全屏时渲染的HTML元素,
  208. useDefaultRenderLoop: true, // 如果需要控制渲染循环,则设为true
  209. targetFrameRate: undefined, // 使用默认render loop时的帧率
  210. showRenderLoopErrors: false, // 如果设为true,将在一个HTML面板中显示错误信息
  211. automaticallyTrackDataSourceClocks: true, // 自动追踪最近添加的数据源的时钟设置
  212. sceneMode: Cesium.SceneMode.SCENE3D, // 初始场景模式
  213. mapProjection: new Cesium.WebMercatorProjection(), // 地图投影体系
  214. dataSources: new Cesium.DataSourceCollection(), // 需要进行可视化的数据源的集合
  215. });
  216. if (systemConfig.msaaSamples != 0) {
  217. globalVariable.viewer.scene.msaaSamples = systemConfig.msaaSamples;
  218. }
  219. //去除版权标记
  220. globalVariable.viewer._cesiumWidget._creditContainer.style.display =
  221. "none";
  222. resolve();
  223. });
  224. },
  225. mainFunc() {
  226. let that = this;
  227. // camera范围限制
  228. this.bindLimitCameraFunc();
  229. // 取消滑动事件
  230. this.controlCZ(systemConfig.mapControl);
  231. // 自定义滑动事件
  232. this.wetherScroll(this.changeCamera);
  233. window.bindLimitCameraFunc = this.bindLimitCameraFunc;
  234. window.unbindLimitCameraFunc = this.unbindLimitCameraFunc;
  235. // entity点击事件
  236. this.entityClickEvent();
  237. // // 键盘/地图点击事件
  238. // this.singleClick(viewer); // 地图点击
  239. this.singleClick2(); // 模型点击
  240. keyboardMapRoamingInit(globalVariable.viewer);
  241. let keyArr = Object.keys(systemConfig.tilesConfig);
  242. this.yanchiAdd3DTiles(0, keyArr);
  243. // for (let i = 0; i < keyArr.length; i++) {
  244. // const str = keyArr[i];
  245. // globalVariable.tilesArr[str] = this.add3DTilesData(
  246. // systemConfig.dataUrl + str + "/tileset.json", //
  247. // {
  248. // light: systemConfig.tilesConfig[str].light,
  249. // }
  250. // );
  251. // }
  252. // 叫号
  253. this.initJH();
  254. // 水面加载
  255. setTimeout(() => {
  256. that.addWaterPanel();
  257. }, 10000);
  258. },
  259. // 延迟加载模型
  260. yanchiAdd3DTiles(index, keyArr) {
  261. let that = this;
  262. if (index >= keyArr.length) return;
  263. const str = keyArr[index];
  264. globalVariable.tilesArr[str] = this.add3DTilesData(
  265. systemConfig.tilesConfig[str].dataUrl + str + "/tileset.json"
  266. );
  267. setTimeout(() => {
  268. that.yanchiAdd3DTiles(++index, keyArr);
  269. }, systemConfig.tilesConfig[str].yanchi);
  270. },
  271. // entity Click
  272. entityClickEvent() {
  273. let viewClickHandle = new Cesium.ScreenSpaceEventHandler(
  274. globalVariable.viewer.scene.canvas
  275. );
  276. viewClickHandle.setInputAction(function (evt) {
  277. var pickedObject = globalVariable.viewer.scene.pick(evt.position);
  278. if (pickedObject && pickedObject.id) {
  279. var clickMarkerId = pickedObject.id._id;
  280. if (globalVariable.point_positions[clickMarkerId]) {
  281. var data = globalVariable.point_positions[clickMarkerId];
  282. if (data.callback) {
  283. data.callback(data.infos);
  284. }
  285. }
  286. } else {
  287. return false;
  288. }
  289. }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  290. },
  291. changeCamera(direction) {
  292. switch (direction) {
  293. case "left":
  294. globalVariable.viewer.camera.lookLeft((Math.PI / 180) * 2);
  295. break;
  296. case "right":
  297. globalVariable.viewer.camera.lookRight((Math.PI / 180) * 2);
  298. break;
  299. default:
  300. break;
  301. }
  302. },
  303. wetherScroll(func) {
  304. let startX = 0;
  305. let endX = 0;
  306. let distanceX = 0;
  307. let body = document.getElementById("cesiumContainer");
  308. var clientWidth = document.documentElement.clientWidth;
  309. body.addEventListener("touchstart", function (event) {
  310. var touch = event.targetTouches[0];
  311. //滑动起点的坐标
  312. startX = touch.pageX;
  313. // console.log("startX:"+startX+","+"startY:"+startY);
  314. });
  315. body.addEventListener("touchmove", function (event) {
  316. var touch = event.targetTouches[0];
  317. //手势滑动时,手势坐标不断变化,取最后一点的坐标为最终的终点坐标
  318. endX = touch.pageX;
  319. distanceX = endX - startX;
  320. if (startX != Math.abs(distanceX)) {
  321. //在滑动的距离超过屏幕高度的20%时,做某种操作
  322. if (Math.abs(distanceX) > clientWidth * 0.001) {
  323. //向下滑实行函数someAction1,向上滑实行函数someAction2
  324. //向左滑实行函数someAction1,向右滑实行函数someAction2
  325. distanceX > 0 ? func("left") : func("right");
  326. startX = endX;
  327. }
  328. }
  329. });
  330. body.addEventListener("touchend", function (event) {
  331. startX = 0;
  332. endX = 0;
  333. distanceX = 0;
  334. });
  335. },
  336. // 禁用/开启 操作
  337. controlCZ(bool) {
  338. let screenSpaceCameraController =
  339. globalVariable.viewer.scene.screenSpaceCameraController;
  340. screenSpaceCameraController.enableLook = bool;
  341. screenSpaceCameraController.enableRotate = bool; // 禁止旋转
  342. screenSpaceCameraController.enableTilt = bool; // 禁止倾斜相机
  343. screenSpaceCameraController.enableTranslate = bool; // 禁止移动
  344. screenSpaceCameraController.enableZoom = bool; // 禁止缩放
  345. },
  346. // 默认定位
  347. setViewDefaultlocation() {
  348. return new Promise((resolve, reject) => {
  349. this.$flyTo({
  350. lon: systemConfig.mapDefault.center.lon,
  351. lat: systemConfig.mapDefault.center.lat,
  352. h: systemConfig.mapDefault.height,
  353. heading: systemConfig.mapDefault.heading,
  354. pitch: systemConfig.mapDefault.pitch,
  355. roll: systemConfig.mapDefault.roll,
  356. time: 1,
  357. pitchAdjustHeight: 1000,
  358. callback: null,
  359. }).then(() => {
  360. resolve();
  361. });
  362. });
  363. },
  364. flyTo(item) {
  365. return new Promise((resolve, reject) => {
  366. globalVariable.viewer.camera.flyTo({
  367. destination: Cesium.Cartesian3.fromDegrees(
  368. item.lon,
  369. item.lat,
  370. item.h
  371. ),
  372. orientation: {
  373. heading: Cesium.Math.toRadians(item.heading), // 方向
  374. pitch: Cesium.Math.toRadians(item.pitch), // 倾斜角度
  375. roll: Cesium.Math.toRadians(item.roll),
  376. },
  377. duration: isNaN(item.time) ? 2 : item.time,
  378. pitchAdjustHeight: item.pitchAdjustHeight || 1000,
  379. complete: function () {
  380. if (item) {
  381. if (item.callback) item.callback(item);
  382. }
  383. resolve();
  384. },
  385. });
  386. });
  387. },
  388. // cesium 球体配置
  389. mapConfig() {
  390. // 大气效果(发光)
  391. globalVariable.viewer.scene.globe.showGroundAtmosphere = false;
  392. // 是否将地球渲染为半透明的球体
  393. globalVariable.viewer.scene.globe.translucency.enabled = true;
  394. // 基础球体颜色
  395. globalVariable.viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT;
  396. // 地底颜色
  397. globalVariable.viewer.scene.globe.undergroundColor = undefined;
  398. // 开启场景光照
  399. globalVariable.viewer.scene.globe.enableLighting = true;
  400. // 控制太阳光
  401. globalVariable.viewer.scene.sun.show = false; // systemConfig.sunShow;
  402. // 控制阴影
  403. globalVariable.viewer.shadows = false; // systemConfig.shadows;
  404. // 阴影强度
  405. globalVariable.viewer.shadowMap.darkness = systemConfig.shadowMapDarkness;
  406. // globalVariable.viewer.terrainShadows = Cesium.ShadowMode.RECEIVE_ONLY;
  407. // // globalVariable.viewer.shadowMap.softShadows = truee
  408. // globalVariable.viewer.shadowMap.darkness = 0.7; //阴影透明度--越大越透明
  409. if (systemConfig.DirectionalLightShow) {
  410. globalVariable.viewer.scene.light = new Cesium.DirectionalLight({
  411. color: new Cesium.Color(
  412. systemConfig.DirectionalLightColor.r,
  413. systemConfig.DirectionalLightColor.g,
  414. systemConfig.DirectionalLightColor.b,
  415. systemConfig.DirectionalLightColor.a
  416. ),
  417. // //去除时间原因影响模型颜色
  418. // direction: Cesium.Cartesian3.fromDegrees(
  419. // 121.1217914833498,
  420. // 31.154385387088624,
  421. // 2000
  422. // ),
  423. direction: new Cesium.Cartesian3(
  424. systemConfig.DirectionalLightDirection.x,
  425. systemConfig.DirectionalLightDirection.y,
  426. systemConfig.DirectionalLightDirection.z
  427. ),
  428. intensity: systemConfig.DirectionalLightIntensity,
  429. });
  430. }
  431. // globalVariable.viewer._cesiumWidget._supportsImageRenderingPixelated =
  432. // Cesium.FeatureDetection.supportsImageRenderingPixelated();
  433. // globalVariable.viewer._cesiumWidget._forceResize = true;
  434. // 解决抗锯齿问题
  435. // // 方法一
  436. // if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
  437. // //判断是否支持图像渲染像素化处理
  438. // var vtxf_dpr = window.devicePixelRatio;
  439. // // 适度降低分辨率
  440. // while (vtxf_dpr >= 2.0) {
  441. // vtxf_dpr /= 2.0;
  442. // }
  443. // //alert(dpr);
  444. // globalVariable.viewer.resolutionScale = vtxf_dpr;
  445. // }
  446. // 方法二
  447. if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
  448. //判断是否支持图像渲染像素化处理
  449. var vtxf_dpr = window.devicePixelRatio;
  450. globalVariable.viewer.resolutionScale = vtxf_dpr;
  451. }
  452. // //是否开启抗锯齿
  453. globalVariable.viewer.scene.fxaa = systemConfig.fxaa;
  454. globalVariable.viewer.scene.postProcessStages.fxaa.enabled =
  455. systemConfig.fxaaEnabled;
  456. // // 天空盒隐藏
  457. // globalVariable.viewer.scene.skyBox.show = false;
  458. // 配置天空盒子
  459. this.deploySkyBox();
  460. },
  461. // 限制camera的移动范围
  462. bindLimitCameraFunc() {
  463. globalVariable.viewer.camera.changed.addEventListener(
  464. this.limitCameraFunc
  465. );
  466. },
  467. unbindLimitCameraFunc() {
  468. globalVariable.viewer.camera.changed.removeEventListener(
  469. this.limitCameraFunc
  470. );
  471. },
  472. limitCameraFunc() {
  473. let that = this;
  474. if (!this.correctCamera) {
  475. this.getNowCameraPosition()
  476. .then((result) => {
  477. let cameraLon = result.result.lon;
  478. let cameraLat = result.result.lat;
  479. let cameraHeight = result.result.h;
  480. if (
  481. cameraLon > systemConfig.mapDefault.bbox.east ||
  482. cameraLon < systemConfig.mapDefault.bbox.west ||
  483. cameraLat > systemConfig.mapDefault.bbox.north ||
  484. cameraLat < systemConfig.mapDefault.bbox.south ||
  485. cameraHeight > systemConfig.mapDefault.defaultH
  486. ) {
  487. that.correctCamera = true;
  488. that.setViewDefaultlocation().then(() => {
  489. huifu();
  490. });
  491. }
  492. cameraLon = null;
  493. cameraLat = null;
  494. cameraHeight = null;
  495. })
  496. .catch((err) => { });
  497. }
  498. function huifu() {
  499. that.correctCamera = false;
  500. }
  501. },
  502. // 配置天空盒
  503. deploySkyBox() {
  504. // 自定义的近地天空盒
  505. let groundSkybox = new Cesium.GroundSkyBox({
  506. sources: {
  507. negativeX: "./static/images/skybox/Left.jpg",
  508. negativeY: "./static/images/skybox/Front.jpg",
  509. negativeZ: "./static/images/skybox/Down.jpg",
  510. positiveX: "./static/images/skybox/Right.jpg",
  511. positiveY: "./static/images/skybox/Back.jpg",
  512. positiveZ: "./static/images/skybox/Up.jpg",
  513. },
  514. });
  515. // // 自带的默认天空盒
  516. // let defaultSkybox = viewer.scene.skyBox;
  517. globalVariable.viewer.scene.skyBox = groundSkybox;
  518. globalVariable.viewer.scene.skyAtmosphere.show = false;
  519. },
  520. // 获取当前camera的详细位置
  521. getNowCameraPosition() {
  522. return new Promise((resolve, reject) => {
  523. var camera = globalVariable.viewer.camera;
  524. var heading = Cesium.Math.toDegrees(
  525. globalVariable.viewer.camera.heading
  526. );
  527. var pitch = Cesium.Math.toDegrees(globalVariable.viewer.camera.pitch); //Cesium.Math.toDegrees作用是把弧度转换成度数
  528. var roll = Cesium.Math.toDegrees(globalVariable.viewer.camera.roll);
  529. var h = globalVariable.viewer.camera.positionCartographic.height;
  530. var camera = globalVariable.viewer.camera.position;
  531. var position = Cesium.Cartographic.fromCartesian(camera);
  532. var lon = Cesium.Math.toDegrees(position.longitude);
  533. var lat = Cesium.Math.toDegrees(position.latitude);
  534. resolve({
  535. str: "",
  536. result: {
  537. lon: lon,
  538. lat: lat,
  539. h: h,
  540. heading: heading,
  541. pitch: pitch,
  542. roll: roll,
  543. },
  544. });
  545. });
  546. // that.showInfoDailog(str);
  547. },
  548. // 地图(地球表面,无地形)左击事件
  549. singleClick() {
  550. var handler = new Cesium.ScreenSpaceEventHandler(
  551. globalVariable.viewer.scene.canvas
  552. );
  553. handler.setInputAction(function (event) {
  554. var earthPosition = globalVariable.viewer.camera.pickEllipsoid(
  555. event.position,
  556. globalVariable.viewer.scene.globe.ellipsoid
  557. );
  558. var cartographic = Cesium.Cartographic.fromCartesian(
  559. earthPosition,
  560. globalVariable.viewer.scene.globe.ellipsoid,
  561. new Cesium.Cartographic()
  562. );
  563. var lat = Cesium.Math.toDegrees(cartographic.latitude);
  564. var lng = Cesium.Math.toDegrees(cartographic.longitude);
  565. var height = cartographic.height;
  566. console.log(lng + "," + lat);
  567. }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  568. },
  569. // 地图(模型上)左击事件
  570. singleClick2() {
  571. let that = this;
  572. var handler = new Cesium.ScreenSpaceEventHandler(
  573. globalVariable.viewer.scene.canvas
  574. );
  575. handler.setInputAction(function (event) {
  576. var pick = globalVariable.viewer.scene.pickPosition(event.position);
  577. var pickModel = globalVariable.viewer.scene.pick(event.position);
  578. if (pickModel && pick && !pickModel.id) {
  579. var height = Cesium.Cartographic.fromCartesian(pick).height;
  580. var lat = Cesium.Math.toDegrees(
  581. Cesium.Cartographic.fromCartesian(pick).latitude
  582. );
  583. var lon = Cesium.Math.toDegrees(
  584. Cesium.Cartographic.fromCartesian(pick).longitude
  585. );
  586. // cartesian = Cesium.Cartesian3.fromDegrees(lng, lat, height);
  587. // console.log("模型高度点", cartesian);
  588. let str = `
  589. lon:${lon},
  590. lat:${lat},
  591. height:${height}
  592. `;
  593. console.log(str);
  594. that.showInfoDailog(
  595. JSON.stringify({
  596. lon: lon,
  597. lat: lat,
  598. h: height,
  599. })
  600. .replaceAll("{", "")
  601. .replaceAll("}", "")
  602. );
  603. }
  604. }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  605. },
  606. /* ------------叫号------------ */
  607. initJH() {
  608. let that = this;
  609. this.initWindowBackground();
  610. window.openJH = this.openJH;
  611. window.closeJH = this.closeJH;
  612. window.showJH = this.showJH;
  613. window.hideJH = this.hideJH;
  614. window.getToken = function () {
  615. return that.$store.getters.getToken;
  616. };
  617. // this.getToken().then(() => {
  618. serviceWindow.map(function (item, index) {
  619. let pointArr = item.topPoint
  620. .map(function (item_) {
  621. return [item_.lon, item_.lat, item_.height];
  622. })
  623. .join()
  624. .split(",")
  625. .map((num) => Number(num));
  626. if (item.type == 1) {
  627. // that.getWindowInfo(item).then((info) => {
  628. // let image = that.createJHImage(item, info);
  629. // let entity = globalVariable.viewer.entities.add({
  630. // wall: {
  631. // positions:
  632. // Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
  633. // minimumHeights: item.endHeight,
  634. // material: new Cesium.ImageMaterialProperty({
  635. // image: image,
  636. // transparent: false,
  637. // }),
  638. // },
  639. // });
  640. // globalVariable.JHEntityObj[item.id] = {
  641. // item: item,
  642. // entity: entity,
  643. // };
  644. // });
  645. let entity = globalVariable.viewer.entities.add({
  646. wall: {
  647. positions: Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
  648. minimumHeights: item.endHeight,
  649. material: Cesium.Color.BLACK,
  650. // material: new Cesium.ImageMaterialProperty({
  651. // image: image,
  652. // transparent: false,
  653. // }),
  654. },
  655. });
  656. if (item.id != "")
  657. globalVariable.JHEntityObj[item.id] = {
  658. item: item,
  659. entity1: entity,
  660. };
  661. } else {
  662. let image = that.createJHImage(item);
  663. let entity = globalVariable.viewer.entities.add({
  664. wall: {
  665. positions: Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
  666. minimumHeights: item.endHeight,
  667. material: new Cesium.ImageMaterialProperty({
  668. image: image,
  669. transparent: false,
  670. }),
  671. },
  672. });
  673. if (item.id != "")
  674. globalVariable.JHEntityObj[item.id] = {
  675. item: item,
  676. entity1: entity,
  677. };
  678. }
  679. });
  680. // });
  681. that.roundJH = true;
  682. // 开始循环访问
  683. that.loopJH();
  684. // 开始循环访问
  685. window.setInterval(function () {
  686. that.loopJH();
  687. }, serviceWindowTime);
  688. },
  689. initWindowBackground() {
  690. // let width = 300,
  691. // height = 100;
  692. // var canvas = document.createElement("canvas");
  693. // canvas.width = 300;
  694. // canvas.height = 100;
  695. // var ctx = canvas.getContext("2d");
  696. // ctx.clearRect(0, 0, width, height);
  697. // // 背景黑色填充
  698. // ctx.fillStyle = "#000000";
  699. // ctx.fillRect(0, 0, width, height);
  700. // let image = canvas.toDataURL("image/png");
  701. this.windowBackgroundArr = windowBackground.map(function (item, index) {
  702. let pointArr = item.topPoint
  703. .map(function (item_) {
  704. return [item_.lon, item_.lat, item_.height];
  705. })
  706. .join()
  707. .split(",")
  708. .map((num) => Number(num));
  709. return globalVariable.viewer.entities.add({
  710. wall: {
  711. positions: Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
  712. minimumHeights: item.endHeight,
  713. material: Cesium.Color.BLACK,
  714. // new Cesium.ImageMaterialProperty({
  715. // image: Cesium.Color.BLACK,
  716. // transparent: false,
  717. // }),
  718. },
  719. });
  720. });
  721. },
  722. openJH() {
  723. this.roundJH = true;
  724. },
  725. closeJH() {
  726. this.roundJH = false;
  727. },
  728. showJH(floor) {
  729. let arr = Object.getOwnPropertyNames(globalVariable.JHEntityObj);
  730. arr.map(function (id) {
  731. let info = globalVariable.JHEntityObj[id];
  732. if (floor) {
  733. if (info.item.floor == floor) {
  734. if (info.entity1) info.entity1.show = true;
  735. if (info.entity2) info.entity2.show = true;
  736. }
  737. } else {
  738. if (info.entity1) info.entity1.show = true;
  739. if (info.entity2) info.entity2.show = true;
  740. }
  741. });
  742. this.windowBackgroundArr.map(function (item) {
  743. item.show = true;
  744. });
  745. },
  746. hideJH(floor) {
  747. let arr = Object.getOwnPropertyNames(globalVariable.JHEntityObj);
  748. arr.map(function (id) {
  749. let info = globalVariable.JHEntityObj[id];
  750. if (floor) {
  751. if (info.item.floor == floor) {
  752. if (info.entity1) info.entity1.show = false;
  753. if (info.entity2) info.entity2.show = false;
  754. }
  755. } else {
  756. if (info.entity1) info.entity1.show = false;
  757. if (info.entity2) info.entity2.show = false;
  758. }
  759. });
  760. this.windowBackgroundArr.map(function (item) {
  761. item.show = false;
  762. });
  763. },
  764. getToken() {
  765. let that = this;
  766. return new Promise((resolve, reject) => {
  767. api.getToken().then(function (result) {
  768. that.$store.commit("setToken", result.data);
  769. resolve();
  770. }, function (err) {
  771. reject(err);
  772. });
  773. });
  774. },
  775. getWindowInfo(params) {
  776. return new Promise((resolve, reject) => {
  777. api.getWindowInfo({ id: params.id }).then(function (result) {
  778. resolve(
  779. result.data != null
  780. ? result.data
  781. : {
  782. win_status: "STOP",
  783. }
  784. );
  785. }, function (err) {
  786. resolve({
  787. win_status: "STOP",
  788. })
  789. });
  790. });
  791. },
  792. createJHImage(item, info) {
  793. // win_code: "A02",
  794. // win_id: "102",
  795. // area_id: "310000310100310118001",
  796. // win_status: "STOP",
  797. // user_code: "742",
  798. // user_name: "谢晨 ",
  799. // ticket_uuid: "",
  800. // ticket_code: "",
  801. let width = 300,
  802. height = 100;
  803. var canvas = document.createElement("canvas");
  804. canvas.width = 300;
  805. canvas.height = 100;
  806. var ctx = canvas.getContext("2d");
  807. ctx.clearRect(0, 0, width, height);
  808. // 背景黑色填充
  809. ctx.fillStyle = "#000000";
  810. ctx.fillRect(0, 0, width, height);
  811. // 窗口编号
  812. ctx.fillStyle = "#FF0000";
  813. ctx.font = "30px Arial";
  814. ctx.fillText(item.id, 15, 60);
  815. // ctx.fillText(info.win_code, 15, 60);
  816. // 红色数线
  817. ctx.fillStyle = "#FF0000";
  818. ctx.beginPath();
  819. ctx.lineWidth = "2";
  820. ctx.strokeStyle = "#FF0000"; // Green path
  821. ctx.moveTo(83, 10);
  822. ctx.lineTo(83, 90);
  823. ctx.stroke(); // Draw it
  824. /* 标题和叫号 */
  825. ctx.fillStyle = "#FF0000";
  826. let maxWidth = 183;
  827. let row = 1;
  828. if (item.title != "") ++row;
  829. if (item.subtitle != "") ++row;
  830. if (item.type == 1) {
  831. if (row == 2) {
  832. if (item.title.length * 30 > maxWidth) {
  833. let num = maxWidth / item.title.length;
  834. ctx.font = num + "px Arial";
  835. ctx.fillText(item.title, 100, (30 - num) / 2 + 15 + num);
  836. } else {
  837. let start = (maxWidth - item.title.length * 30) / 2 + 100;
  838. ctx.font = "30px Arial";
  839. ctx.fillText(item.title, start, 45);
  840. }
  841. if (info.win_status == "STOP") {
  842. ctx.font = "30px Arial";
  843. ctx.fillText("暂停服务", 130, 83);
  844. } else {
  845. if (info.ticket_code == "") {
  846. ctx.font = "30px Arial";
  847. ctx.fillText("欢迎光临", 130, 83);
  848. } else {
  849. ctx.font = "30px Arial";
  850. ctx.fillText("请" + info.ticket_code + "号", 112, 83);
  851. }
  852. }
  853. } else if (row == 3) {
  854. if (item.title.length * 20 > maxWidth) {
  855. let num = maxWidth / item.title.length;
  856. ctx.font = num + "px Arial";
  857. ctx.fillText(item.title, 100, (20 - num) / 2 + 10 + num);
  858. } else {
  859. let start = (maxWidth - item.title.length * 20) / 2 + 100;
  860. ctx.font = "20px Arial";
  861. ctx.fillText(item.title, start, 30);
  862. }
  863. if (item.subtitle.length * 20 > maxWidth) {
  864. let num = maxWidth / item.subtitle.length;
  865. ctx.font = num + "px Arial";
  866. ctx.fillText(
  867. item.subtitle,
  868. 100,
  869. (20 - num) / 2 + 10 + 20 + 10 + num
  870. );
  871. } else {
  872. let start = (maxWidth - item.subtitle.length * 20) / 2 + 100;
  873. ctx.font = "20px Arial";
  874. ctx.fillText(item.subtitle, start, 60);
  875. }
  876. if (info.win_status == "STOP") {
  877. ctx.font = "20px Arial";
  878. ctx.fillText("暂停服务", 153.5, 90);
  879. } else {
  880. if (info.ticket_code == "") {
  881. ctx.font = "20px Arial";
  882. ctx.fillText("欢迎光临", 153.5, 90);
  883. } else {
  884. ctx.font = "20px Arial";
  885. ctx.fillText("请" + info.ticket_code + "号", 140, 90);
  886. }
  887. }
  888. }
  889. } else {
  890. if (row == 1) {
  891. ctx.clearRect(0, 0, width, height);
  892. // 背景黑色填充
  893. ctx.fillStyle = "#000000";
  894. ctx.fillRect(0, 0, width, height);
  895. ctx.fillStyle = "#FF0000";
  896. if (item.name.length * 30 >= 280) {
  897. let num = 300 / item.name.length;
  898. ctx.font = num + "px Arial";
  899. ctx.fillText(item.name, 10, (100 - num) / 2 + num);
  900. } else {
  901. let start = (280 - item.name.length * 30) / 2 + 10;
  902. ctx.font = "30px Arial";
  903. ctx.fillText(item.name, start, 65);
  904. }
  905. } else if (row == 2) {
  906. if (item.title.length * 30 > maxWidth) {
  907. let num = maxWidth / item.title.length;
  908. ctx.font = num + "px Arial";
  909. ctx.fillText(item.title, 100, (30 - num) / 2 + 15 + num);
  910. } else {
  911. let start = (maxWidth - item.title.length * 30) / 2 + 100;
  912. ctx.font = "30px Arial";
  913. ctx.fillText(item.title, start, 45);
  914. }
  915. ctx.font = "30px Arial";
  916. ctx.fillText("欢迎光临", 130, 83);
  917. }
  918. }
  919. return canvas.toDataURL("image/png");
  920. },
  921. loopJH() {
  922. if (!this.roundJH) return;
  923. let that = this;
  924. this.getToken().then(() => {
  925. let arr = Object.getOwnPropertyNames(globalVariable.JHEntityObj);
  926. arr.map(function (index) {
  927. let obj = globalVariable.JHEntityObj[index];
  928. let item = obj.item;
  929. if (item.type == 1) {
  930. that.getWindowInfo(obj.item).then((info) => {
  931. let image = that.createJHImage(item, info);
  932. let pointArr = item.topPoint
  933. .map(function (item_) {
  934. return [item_.lon, item_.lat, item_.height];
  935. })
  936. .join()
  937. .split(",")
  938. .map((num) => Number(num));
  939. globalVariable.JHEntityObj[index].entity2 =
  940. globalVariable.viewer.entities.add({
  941. show: false,
  942. wall: {
  943. positions:
  944. Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
  945. minimumHeights: item.endHeight,
  946. material: new Cesium.ImageMaterialProperty({
  947. image: image,
  948. transparent: false,
  949. }),
  950. },
  951. });
  952. setTimeout(() => {
  953. globalVariable.JHEntityObj[index].entity1.show = false;
  954. if (that.roundJH) {
  955. globalVariable.JHEntityObj[index].entity2.show = true;
  956. } else {
  957. globalVariable.JHEntityObj[index].entity2.show = false;
  958. }
  959. globalVariable.viewer.entities.remove(
  960. globalVariable.JHEntityObj[index].entity1
  961. );
  962. globalVariable.JHEntityObj[index].entity1 =
  963. globalVariable.JHEntityObj[index].entity2;
  964. }, 200);
  965. // obj.entity.wall.material = new Cesium.ImageMaterialProperty({
  966. // image: image,
  967. // transparent: true,
  968. // });
  969. });
  970. }
  971. });
  972. }, function (err) {
  973. console.log(err);
  974. });
  975. },
  976. /* ------------------------ */
  977. // 地图添加图片
  978. addImage(viewer, pObj, imgUrl) {
  979. // // 顺时针
  980. // let pObj = {
  981. // arr: [
  982. // 121.12273519090121, 31.153826679130416, 3.280499471365055,
  983. // 121.12273833983032, 31.153813096263634, 3.281036567079009,
  984. // ],
  985. // minH: [2.807028457880749, 2.807028457880749],
  986. // };
  987. // let imgUrl = '../static/images/ceshi.png';
  988. // let material = Cesium.Material.fromType("Image");
  989. // material.uniforms.image = imgUrl;
  990. return new Promise((resolve, reject) => {
  991. let instance = new Cesium.GeometryInstance({
  992. geometry: new Cesium.WallGeometry({
  993. positions: Cesium.Cartesian3.fromDegreesArrayHeights(pObj.arr),
  994. minimumHeights: pObj.minH,
  995. }),
  996. });
  997. new Cesium.createDynamicImage({
  998. imageWidth: 1000,
  999. imageHeight: 500,
  1000. canvasWidth: 1000,
  1001. canvasHeight: 500,
  1002. period: 60,
  1003. text: "税务综合受理",
  1004. }).then((result) => {
  1005. let material = Cesium.Material.fromType("Image");
  1006. material.uniforms.image = result;
  1007. // 使用抽象的Primitive而不是RectanglePrimitive
  1008. let wallPrimitive = new Cesium.Primitive({
  1009. geometryInstances: instance,
  1010. appearance: new Cesium.MaterialAppearance({
  1011. material: material,
  1012. faceForward: true,
  1013. }),
  1014. });
  1015. viewer.scene.primitives.add(wallPrimitive);
  1016. });
  1017. });
  1018. // return item;
  1019. },
  1020. changeImage(primitiveObj, imgUrl) {
  1021. let material = Cesium.Material.fromType("Image");
  1022. material.uniforms.image = imgUrl;
  1023. primitiveObj.appearance = new Cesium.MaterialAppearance({
  1024. material: material,
  1025. faceForward: true,
  1026. });
  1027. },
  1028. showInfoDailog(str) {
  1029. this.dialogVisible = true;
  1030. this.dialogInfoStr = str;
  1031. },
  1032. hideInfoDailog() {
  1033. this.dialogVisible = false;
  1034. },
  1035. // 添加水面
  1036. addWaterPanel() {
  1037. let d = [];
  1038. for (let i = 0; i < systemConfig.water.length; i += 2) {
  1039. let x = systemConfig.water[i];
  1040. let y = systemConfig.water[i + 1];
  1041. d.push(x);
  1042. d.push(y);
  1043. d.push(1);
  1044. }
  1045. let geometry = new Cesium.PolygonGeometry({
  1046. polygonHierarchy: new Cesium.PolygonHierarchy(
  1047. Cesium.Cartesian3.fromRadiansArrayHeights(d)
  1048. ),
  1049. height: -2,
  1050. });
  1051. let waterFace = this.waterObj.create(geometry, {
  1052. // normalMap: "img/textures/waterNormals.jpg", // 水正常扰动的法线图
  1053. frequency: 8000.0, // 控制波数的数字。
  1054. animationSpeed: 0.02, // 控制水的动画速度的数字。
  1055. amplitude: 5.0, // 控制水波振幅的数字。
  1056. specularIntensity: 0.8, // 控制镜面反射强度的数字。
  1057. baseWaterColor: "#006ab4", // rgba颜色对象基础颜色的水。#00ffff,#00baff,#006ab4
  1058. blendColor: "#006ab4", // 从水中混合到非水域时使用的rgba颜色对象。
  1059. // height: 100, //水面高度
  1060. clampToGround: true, //是否贴地
  1061. opacity: 0.7, //透明度
  1062. });
  1063. globalVariable.viewer.scene.primitives.add(waterFace);
  1064. },
  1065. // 加载3DTiles数据
  1066. add3DTilesData(url, options) {
  1067. if (!options) {
  1068. options = {
  1069. show: true,
  1070. // light: 1,
  1071. matrix: null,
  1072. };
  1073. } else {
  1074. options.show = typeof options.show == "boolean" ? options.show : true;
  1075. // options.light = isNaN(options.light) ? 1 : options.light;
  1076. }
  1077. let that = this;
  1078. let tileset = new Cesium.Cesium3DTileset({
  1079. url: url,
  1080. show: options.show,
  1081. });
  1082. globalVariable.viewer.scene.primitives.add(tileset);
  1083. tileset.readyPromise.then(function () {
  1084. if (options.matrix)
  1085. tileset.root.transform = that.createMatrix4(options.matrix);
  1086. tileset.style = {
  1087. color: {
  1088. conditions: [["true", "rgba(0, 0, 0, 0.3)"]],
  1089. },
  1090. };
  1091. });
  1092. return tileset;
  1093. },
  1094. // 创建偏移矩阵
  1095. createMatrix4(matrixParam, defaultModelMatrix) {
  1096. let tileModelTool = matrixParam;
  1097. var mx = Cesium.Matrix3.fromRotationX(
  1098. Cesium.Math.toRadians(tileModelTool.rx)
  1099. );
  1100. var my = Cesium.Matrix3.fromRotationY(
  1101. Cesium.Math.toRadians(tileModelTool.ry)
  1102. );
  1103. var mz = Cesium.Matrix3.fromRotationZ(
  1104. Cesium.Math.toRadians(tileModelTool.rz)
  1105. );
  1106. var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
  1107. var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
  1108. var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
  1109. var m;
  1110. if (defaultModelMatrix) {
  1111. m = defaultModelMatrix;
  1112. } else {
  1113. //平移 修改经纬度
  1114. var position = Cesium.Cartesian3.fromDegrees(
  1115. tileModelTool.longitude,
  1116. tileModelTool.latitude,
  1117. tileModelTool.height
  1118. );
  1119. m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
  1120. }
  1121. //旋转、平移矩阵相乘
  1122. Cesium.Matrix4.multiply(m, rotationX, m);
  1123. Cesium.Matrix4.multiply(m, rotationY, m);
  1124. Cesium.Matrix4.multiply(m, rotationZ, m);
  1125. //缩放 修改缩放比例
  1126. var scale = Cesium.Matrix4.fromUniformScale(tileModelTool.scale);
  1127. Cesium.Matrix4.multiply(m, scale, m);
  1128. return m;
  1129. },
  1130. },
  1131. };
  1132. </script>
  1133. <style lang="less" scoped>
  1134. .viewer_container {
  1135. width: 100%;
  1136. height: 100%;
  1137. #cesiumContainer {
  1138. width: 100%;
  1139. height: 100%;
  1140. // .get_now_camera_view {
  1141. // position: absolute;
  1142. // z-index: 1;
  1143. // }
  1144. }
  1145. }
  1146. </style>