ViewerSplitScreen.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. <script setup>
  2. import {
  3. inject
  4. } from "vue";
  5. const getMapInstance = inject("getMapInstance");
  6. jt3dRight = getMapInstance();
  7. import {
  8. Store
  9. } from '@/store/index'
  10. store = Store()
  11. import {
  12. deepTree
  13. } from "@/utils/deepTree.js";
  14. </script>
  15. <template>
  16. <div class="jt-layer">
  17. <el-tree :data="treeData" :default-expanded-keys="expandedKeys" :default-checked-keys="checkedkeys" node-key="id" class="tree-line" ref="treeRef">
  18. <template #default="{ node, data }">
  19. <!-- 复选框 -->
  20. <el-checkbox v-if="data.ischeck === '1' && store.userport == 'PC'" v-model="node.checked" :indeterminate="node.indeterminate" :disabled="!!node.disabled" @change="handleCheckBoxChange($event, data, node)">
  21. </el-checkbox>
  22. <el-switch v-else-if="data.ischeck == 1 && store.userport == 'APP'" width="30rem" size="small" v-model="node.checked" @change="handleCheckBoxChange($event, data, node)" />
  23. <span class="custom-tree-node" @click="handleClick(data)" style="width: 150rem;text-align: left;">
  24. <!-- 字体、图标 -->
  25. <!-- <span>
  26. <img src="@/assets/images/logo16x16.ico" />
  27. </span> -->
  28. <span class="overflowtext">
  29. {{ data.layername }}
  30. </span>
  31. </span>
  32. <!-- 透明度 -->
  33. <template v-if="node.checked && data.opacity >0">
  34. <div style="width: 80rem; padding: 0 20rem; position: absolute; right: 0">
  35. <el-slider v-model="data.opacity" @input="handleSliderChange($event, data)" :max="1" :min="0.1" :step="0.1" />
  36. </div>
  37. </template>
  38. </template>
  39. </el-tree>
  40. </div>
  41. </template>
  42. <script>
  43. let store = undefined;
  44. let jt3dRight = undefined;
  45. let jt3dLeft = undefined;
  46. export default {
  47. /* 数据 */
  48. data() {
  49. return {
  50. treeData: [],
  51. inittree: [], //初始化图层数组
  52. expandedKeys: [], //对应要展开的节点id
  53. checkedkeys: [] //默认打开节点的id
  54. }
  55. },
  56. /* 方法 */
  57. methods: {
  58. /**
  59. * 单击图层名称触发服务定位
  60. * @param {Object} data 传递给 data 属性的数组中该节点所对应的对象
  61. */
  62. handleClick(data) {
  63. this.$parent.$parent.$refs.refLayer.mark = "serviceLeft";
  64. this.$parent.$parent.$refs.refLayer.setLayersLocation(jt3dLeft, data);
  65. },
  66. /**
  67. * el-slider 值改变时触发
  68. * 地图服务的透明度调整
  69. */
  70. handleSliderChange($event, data) {
  71. this.$parent.$parent.$refs.refLayer.mark = "serviceLeft";
  72. this.$parent.$parent.$refs.refLayer.setLayersAlpha(jt3dLeft, $event, data)
  73. },
  74. /**
  75. * el-checkbox 当绑定值变化时触发的事件
  76. * @param {Object} checked 复选框状态
  77. * @param {Object} data 对应于节点点击的节点对象
  78. * @param {Object} node TreeNode 的 node 属性
  79. */
  80. handleCheckBoxChange(checked, data, node) {
  81. this.$parent.$parent.$refs.refLayer.mark = "serviceLeft";
  82. let _node = this.$refs.treeRef.getNode(data);
  83. if (_node.isLeaf) {
  84. this.$parent.$parent.$refs.refLayer.setLayersControl(jt3dLeft, data, checked);
  85. this.$refs.treeRef.setChecked(_node, checked); //是否设置子节点,默认为false,利用tree组件渲染后带有的isLeaf(是否为叶子节点)属性,如果为叶子节点就选中。利用tree的API就实现了正确的回显效果
  86. }
  87. //控制子节点
  88. this.childNodesChange(node, checked);
  89. },
  90. /**
  91. * 控制子节点
  92. * @param {Object} node
  93. * @param {Object} checked
  94. */
  95. childNodesChange(node, checked) {
  96. let _self = this;
  97. node.childNodes.forEach(item => {
  98. _self.$parent.$parent.$refs.refLayer.setLayersControl(jt3dLeft, item.data, checked);
  99. _self.$refs.treeRef.setChecked(item, checked);
  100. _self.childNodesChange(item, checked);
  101. });
  102. },
  103. /**
  104. * 分屏对比初始化
  105. */
  106. initSplitScreen() {
  107. let _self = this;
  108. //这样做会跑偏
  109. // let cesiumContainerDiv = document.getElementById("cesiumContainer2");
  110. // if (cesiumContainerDiv == null) {
  111. // cesiumContainerDiv = document.createElement('div');
  112. // cesiumContainerDiv.id = "cesiumContainer2";
  113. // cesiumContainerDiv.classList.add("ViewerSplitScreen");
  114. // cesiumContainerDiv.style.float = "left";
  115. // cesiumContainerDiv.style.width = "calc(50% - 1rem)";
  116. // cesiumContainerDiv.style.height = "100vh";
  117. // cesiumContainerDiv.style.margin = "0";
  118. // cesiumContainerDiv.style.borderRight = "2rem solid red";
  119. // /* 加入到页面 */
  120. // document.body.appendChild(cesiumContainerDiv);
  121. // }
  122. let mapView1 = document.getElementById("cesiumContainer");
  123. let mapView2 = document.getElementById("cesiumContainer2");
  124. mapView1.className = "ViewerSplitScreen";
  125. mapView2.style.display = "block";
  126. //加载分屏左侧大球
  127. this.initMap3d();
  128. //同步相机状态
  129. this.syncViewer();
  130. //绑定图层控制
  131. this.initTree();
  132. },
  133. /**
  134. * 移除分屏对比
  135. */
  136. removeSplitScreen() {
  137. let mapView1 = document.getElementById("cesiumContainer");
  138. let mapView2 = document.getElementById("cesiumContainer2");
  139. mapView1.className = "jt-map";
  140. mapView2.style.display = "none";
  141. mapView2.innerHTML = "";
  142. if (jt3dLeft) {
  143. jt3dLeft._viewer.entities.removeAll(); // 删除全部
  144. jt3dLeft._viewer.imageryLayers.removeAll();
  145. jt3dLeft._viewer.scene.primitives.removeAll(); //谨慎使用,可能删除不必要的primitive
  146. // jt3dLeft._viewer.destroy();
  147. jt3dLeft = undefined;
  148. }
  149. },
  150. /**
  151. * 加载分屏左侧大球
  152. */
  153. initMap3d() {
  154. jt3dLeft = new this.jt3dSDK.jtMap3d({
  155. container: "cesiumContainer2",
  156. });
  157. //底部工具
  158. jt3dLeft.statusBar.show = true;
  159. //图层
  160. jt3dLeft.layer = new this.jt3dSDK.layer(jt3dLeft._viewer);
  161. //测量工具
  162. jt3dLeft.CommonTools = new this.jt3dSDK.CommonTools(jt3dLeft._viewer);
  163. //绘图工具
  164. jt3dLeft.SketchViewModel = new this.jt3dSDK.SketchViewModel(jt3dLeft._viewer, {
  165. isClear: false,
  166. isDrawPoint: true,
  167. isRetainDrawPoint: true,
  168. iconType: 'blue',
  169. });
  170. //定位工具
  171. jt3dLeft.LocateUtil = new this.jt3dSDK.LocateUtil(jt3dLeft._viewer);
  172. //二三维标绘
  173. jt3dLeft.DrawTools = new this.jt3dSDK.DrawTools(jt3dLeft._viewer);
  174. //军事标绘
  175. jt3dLeft.DrawMilitaryPlot = new this.jt3dSDK.DrawMilitaryPlot(jt3dLeft._viewer);
  176. //天空盒子
  177. jt3dLeft.SceneEffects = {};
  178. jt3dLeft.SceneEffects.SkyBox = new this.jt3dSDK.SceneEffects.SkyBox(jt3dLeft._viewer);
  179. //线对象
  180. jt3dLeft.PolylineObject = new this.jt3dSDK.PolylineObject(jt3dLeft._viewer);
  181. //比例尺、指南针
  182. this.$parent.$parent.$refs.refNavigation.initNavigation(jt3dLeft);
  183. //设置默认视图
  184. this.$parent.$parent.$refs.refMap3d.setView(jt3dLeft);
  185. // 初始化项目区域范围视角
  186. this.$parent.$parent.$refs.refMap3d.fullMap(jt3dLeft);
  187. //加载天空盒子
  188. this.$parent.$parent.$refs.refMap3d.addSkybox(jt3dLeft);
  189. //添加镇街边界线——精灵线
  190. // this.$parent.$parent.$refs.refMap3d.addBoundaryLine(jt3dLeft);
  191. },
  192. /**
  193. * 同步相机状态
  194. */
  195. syncViewer() {
  196. let _self = this;
  197. let viewerL = jt3dLeft._viewer;
  198. let viewerR = jt3dRight._viewer;
  199. var sceneL = viewerL.scene;
  200. var sceneR = viewerR.scene;
  201. var handlerL = new Cesium.ScreenSpaceEventHandler(sceneL.canvas);
  202. var ellipsoidL = sceneL.globe.ellipsoid;
  203. var handlerR = new Cesium.ScreenSpaceEventHandler(sceneR.canvas);
  204. var ellipsoidR = sceneR.globe.ellipsoid;
  205. handlerL.setInputAction((movement) => {
  206. this.isLeftTrigger = true;
  207. this.isRightTrigger = false;
  208. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  209. handlerR.setInputAction((movement) => {
  210. this.isLeftTrigger = false;
  211. this.isRightTrigger = true;
  212. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  213. var syncViewerL = function() {
  214. if (_self.isLeftTrigger) {
  215. viewerR.camera.flyTo({
  216. destination: viewerL.camera.position,
  217. orientation: {
  218. heading: viewerL.camera.heading,
  219. pitch: viewerL.camera.pitch,
  220. roll: viewerL.camera.roll
  221. },
  222. duration: 0.0
  223. });
  224. }
  225. }
  226. viewerR.camera.changed.addEventListener(syncViewerL);
  227. viewerR.scene.preRender.addEventListener(syncViewerL);
  228. var syncViewerR = function() {
  229. if (_self.isRightTrigger) {
  230. viewerL.camera.flyTo({
  231. destination: viewerR.camera.position,
  232. orientation: {
  233. heading: viewerR.camera.heading,
  234. pitch: viewerR.camera.pitch,
  235. roll: viewerR.camera.roll
  236. },
  237. duration: 0.0
  238. });
  239. }
  240. }
  241. viewerR.camera.changed.addEventListener(syncViewerR);
  242. viewerR.scene.preRender.addEventListener(syncViewerR);
  243. },
  244. /**
  245. * 加载图层控制树
  246. */
  247. initTree() {
  248. this.$parent.$parent.$refs.refLayer.mark = "serviceLeft";
  249. //在这获取图层列表
  250. let _this = this
  251. //权限查询条件语句
  252. let atlasLayersSqlWhere = undefined
  253. //获取地图图集id
  254. let roleId = store.roleId
  255. atlasLayersSqlWhere = '"roleId"' + " = " + roleId + " "
  256. //Promise回调
  257. function init(data) {
  258. return new Promise((resolve, reject) => {
  259. _this.inittree.forEach(res => {
  260. let num = Number(res.layerorder)
  261. if (num < 10) {
  262. res.layerorder = '0' + res.layerorder
  263. }
  264. //透明度
  265. res.opacity = Number(res.opacity);
  266. //默认展开
  267. if (res.isexpand === '1') {
  268. _this.expandedKeys.push(res.id);
  269. }
  270. // 复选框默认选中
  271. if (res.isinit === '1') {
  272. _this.checkedkeys.push(res.id);
  273. _this.$parent.$parent.$refs.refLayer.setLayersControl(jt3dLeft, res, true);
  274. }
  275. })
  276. _this.treeData = deepTree(_this.inittree)
  277. resolve(_this.treeData)
  278. })
  279. }
  280. //获取图集
  281. this.$http.get('/getTableList', {
  282. tableName: 'sys_map_atlas_layers', //表名
  283. sqlWhere: atlasLayersSqlWhere, //
  284. orderByField: ''
  285. }).then(res => {
  286. console.log('所有图层', res.data)
  287. //初始图层列表
  288. this.inittree = res.data
  289. init(res.data).then(item => {
  290. console.log('图层控制树列表', _this.treeData)
  291. //复选框初始化选中
  292. _this.$nextTick(() => {
  293. _this.$refs.treeRef.setCheckedKeys(_this.checkedkeys, true);
  294. });
  295. })
  296. })
  297. }
  298. },
  299. mounted() {
  300. },
  301. };
  302. </script>
  303. <style lang="scss">
  304. .el-switch--small .el-switch__core .el-switch__action {
  305. width: 12rem;
  306. height: 12rem;
  307. }
  308. .el-switch--small.is-checked .el-switch__core .el-switch__action {
  309. margin-left: calc(-1rem - 12rem);
  310. }
  311. .el-switch__core .el-switch__action {
  312. top: 0;
  313. }
  314. .el-slider__button {
  315. width: 20rem;
  316. height: 20rem;
  317. }
  318. .el-tree-node__content {
  319. height: 26rem;
  320. }
  321. .el-switch--small .el-switch__core {
  322. height: 16rem;
  323. }
  324. .el-switch--small {
  325. padding: 0 5rem;
  326. }
  327. .jt-layer {
  328. padding-left: 10rem;
  329. .el-tree {
  330. background: none;
  331. color: #fff;
  332. --el-tree-node-hover-bg-color: #2a67c3;
  333. .overflowtext {
  334. width: auto !important;
  335. padding: 0;
  336. }
  337. }
  338. .tree-line {
  339. .el-tree-node {
  340. position: relative;
  341. // padding-left: 16rem; // 缩进量
  342. }
  343. .el-tree-node__children {
  344. padding-left: 16rem !important; // 缩进量
  345. .el-tree-node__content {
  346. padding-left: 18rem !important;
  347. }
  348. }
  349. // 竖线
  350. .el-tree-node::before {
  351. content: "";
  352. height: 100%;
  353. width: 1rem;
  354. position: absolute;
  355. left: -3rem;
  356. top: -26rem;
  357. border-width: 1rem;
  358. border-left: 1rem dashed rgba(255, 255, 255, .8);
  359. }
  360. // 当前层最后一个节点的竖线高度固定
  361. .el-tree-node:last-child::before {
  362. height: 38rem; // 可以自己调节到合适数值
  363. }
  364. // 横线
  365. .el-tree-node::after {
  366. content: "";
  367. width: 24rem;
  368. height: 20rem;
  369. position: absolute;
  370. left: -3rem;
  371. top: 12rem;
  372. border-width: 1rem;
  373. border-top: 1rem dashed rgba(255, 255, 255, .8);
  374. }
  375. // 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
  376. &>.el-tree-node::after {
  377. border-top: none;
  378. }
  379. &>.el-tree-node::before {
  380. border-left: none;
  381. }
  382. // 展开关闭的icon
  383. .el-tree-node__expand-icon {
  384. font-size: 16rem;
  385. // 叶子节点(无子节点)
  386. &.is-leaf {
  387. color: transparent;
  388. display: none; // 也可以去掉
  389. }
  390. }
  391. }
  392. }
  393. </style>