08d179dd4c373efdaaeb7c0e49dadd0d6e934a9c.svn-base 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <template>
  2. <div>
  3. <div id="toolBar" class="toolBar ol-unselectable">
  4. <ul class="nav nav-pills">
  5. <li v-if="isRes"
  6. @click="resShow=!resShow;coordsShow=false;measureShow=false;queryShow=false;drawShow = false;">
  7. <a><img
  8. src="@/assets/layers.png" width="24"> 图层</a></li>
  9. <res-catalog v-if="isRes" id="resourceCatalog" v-model="resShow"></res-catalog>
  10. <li v-if="isQuery" @click="queryShow=!queryShow; resShow=false;coordsShow=false;measureShow=false;drawShow = false;">
  11. <a><img src="@/assets/query.png" width="24"> 查询</a>
  12. </li>
  13. <query-tool v-if="isQuery" id="queryTool" ref="queryTool" v-model="queryShow"></query-tool>
  14. <li v-if="isCoords"
  15. @click="coordsShow=!coordsShow;resShow=false;measureShow=false;queryShow=false;drawShow = false;">
  16. <a><img
  17. src="@/assets/locationTool.png" width="24"> 定位</a></li>
  18. <coords-locate v-if="isCoords" id="coordsLocate" ref="coordsLocate"
  19. v-model="coordsShow"></coords-locate>
  20. <!-- <li v-if="isExtent" id="zoomToFullExtent" @click="zoomToFullExtent"><a><img src="@/assets/ZoomFullExtent.png" width="24">
  21. 全图</a></li>-->
  22. <li v-if="isMeasure" @click="handleMeasure"><a><img src="@/assets/measureTool.png" width="24"> 测量</a>
  23. </li>
  24. <measure-tool v-if="isMeasure" ref="measureToll" id="measureTool" v-model="measureShow"
  25. :output.sync="output"></measure-tool>
  26. <li v-if="isDraw" @click="handleDrawTool"><a><img
  27. src="@/assets/drawPencil.png" width="24"> 标绘</a></li>
  28. <draw-tool v-if="isDraw" ref="drawTool" id="drawTool" v-model="drawShow"></draw-tool>
  29. <li v-if="isClear" id="clearTool" @click="handleClear"><a><img src="@/assets/clear.png" width="24">
  30. 清除</a></li>
  31. </ul>
  32. </div>
  33. <!-- 点选查询弹框-->
  34. <div class="ant-popover ant-popover-placement-top popup" id="popup" ref="popup" v-show="tabs.length!==0">
  35. <div class="ant-popover-content">
  36. <div class="ant-popover-arrow"></div>
  37. <div role="tooltip" class="ant-popover-inner">
  38. <div>
  39. <div class="ant-popover-inner-content">
  40. <div style="width: 320px">
  41. <a-tabs default-active-key="1" tab-position="top" :style="{ 'min-height': '200px' }">
  42. <a-tab-pane v-for="(tab,i) in tabs" :key="i" :tab="tab.name">
  43. <a-descriptions bordered :column='1'>
  44. <a-descriptions-item v-for="(item,index) in tab.inner" :label="item.label">
  45. {{ item.content }}
  46. </a-descriptions-item>
  47. </a-descriptions>
  48. </a-tab-pane>
  49. </a-tabs>
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. </template>
  58. <script>
  59. import * as olEasing from 'ol/easing';
  60. import axios from "axios";
  61. import Overlay from "ol/Overlay";
  62. import {getAction} from "../../../api/manage";
  63. // 组件
  64. import CoordsLocate from '@/components/BasicMap/Tools/CoordsLocate.vue';
  65. import ResCatalog from "@/components/BasicMap/Tools/ResCatalog";
  66. import MeasureTool from '@/components/BasicMap/Tools/MeasureTool.vue'
  67. import QueryTool from '@/components/BasicMap/Tools/QueryTool.vue'
  68. import DrawTool from '@/components/BasicMap/Tools/DrawTool.vue';
  69. import {DragBox} from "ol/interaction";
  70. import {platformModifierKeyOnly} from "ol/events/condition";
  71. export default {
  72. name: 'Toolbar',
  73. components: {
  74. CoordsLocate,
  75. ResCatalog,
  76. MeasureTool,
  77. QueryTool,
  78. DrawTool
  79. },
  80. data() {
  81. return {
  82. isRes: false,
  83. isQuery: false,
  84. isCoords: false,
  85. isMeasure: false,
  86. isDraw: false,
  87. isClear: false,
  88. isExtent: false,
  89. coordsShow: false,
  90. resShow: false,
  91. measureShow: false,
  92. queryShow: false,
  93. drawShow: false,
  94. properties: {},
  95. labels: [],
  96. tabs: [],
  97. map: {},
  98. currentCoordinate: null, // 弹窗坐标数据
  99. overlay: null,
  100. mapCursorKey: '',
  101. output: '',
  102. dataport: '',
  103. relfield: '',
  104. }
  105. },
  106. props: {
  107. tools: {
  108. type: Array,
  109. default: function () {
  110. return []
  111. }
  112. },
  113. splitScreen: {}
  114. },
  115. mounted() {
  116. if (this.tools.length === 0) {
  117. this.isRes = true;
  118. this.isClear = true;
  119. this.isDraw = true;
  120. this.isCoords = true;
  121. this.isExtent = true;
  122. this.isMeasure = true;
  123. this.isQuery = true;
  124. } else {
  125. this.tools.forEach((item) => {
  126. this[item] = true;
  127. })
  128. }
  129. // this.initPopup();
  130. },
  131. watch: {
  132. measureShow: function (newValue) {
  133. if (newValue === false) {
  134. this.$refs.measureToll.closeMeasureTool(this.baseMap.map);
  135. this.baseMap.map.getOverlays().clear();
  136. if (this.drawShow === false) {
  137. this.initPopup();
  138. }
  139. } else {
  140. //移除点击事件
  141. this.map.un(this.mapCursorKey.type, this.mapCursorKey.listener);
  142. this.overlay.setPosition(undefined);
  143. this.currentCoordinate = null;
  144. }
  145. }
  146. },
  147. provide() {
  148. return {
  149. splitScreen: this.splitScreen,
  150. }
  151. },
  152. inject: ['baseMap'],
  153. methods: {
  154. handleDrawTool() {
  155. this.measureShow = false;
  156. this.coordsShow = false;
  157. this.resShow = false;
  158. this.queryShow = false;
  159. this.drawShow = !this.drawShow;
  160. if (this.drawShow) {
  161. this.baseMap.map.getOverlays().clear();
  162. this.$refs.drawTool.initDrawLayer();
  163. // initVectorLayer(this.baseMap.map);
  164. // this.output = initMeasureTool();
  165. }
  166. },
  167. handleMeasure() {
  168. this.measureShow = !this.measureShow;
  169. this.coordsShow = false;
  170. this.resShow = false;
  171. this.queryShow = false;
  172. this.drawShow = false;
  173. if (this.measureShow) {
  174. this.baseMap.map.getOverlays().clear();
  175. this.$refs.measureToll.onChange();
  176. // initVectorLayer(this.baseMap.map);
  177. // this.output = initMeasureTool();
  178. }
  179. },
  180. handleClear() {
  181. this.measureShow = false;
  182. this.coordsShow = false;
  183. this.resShow = false;
  184. this.queryShow = false;
  185. this.drawShow = false;
  186. this.$refs.measureToll.closeMeasureTool(this.baseMap.map);
  187. this.$refs.coordsLocate.resetForm();
  188. this.$refs.queryTool.clear();
  189. this.$refs.drawTool.clearFeature();
  190. },
  191. zoomToFullExtent() {
  192. let extent = [115.75550079345703, 36.407955169677734, 117.60053253173828, 38.01062774658203];
  193. this.baseMap.map.getView().fit(extent, {
  194. // size:[500,300],
  195. duration: 500,
  196. padding: [10, 10, 10, 10],
  197. easing: olEasing.inAndOut
  198. })
  199. },
  200. // 递归查找
  201. getTreeExpandKeys(obj, name) {
  202. // obj是传入的array
  203. if (obj && obj.length !== 0) {
  204. obj.forEach((item, index) => {
  205. if (item.alias === name) {
  206. this.labels = item.fields;
  207. this.relfield = item.relfield;
  208. this.dataport = item.dataport;
  209. return;
  210. }
  211. // 如果此列表有children, 进行递归
  212. if (item.layers) {
  213. this.getTreeExpandKeys(item.layers, name)
  214. }
  215. })
  216. }
  217. },
  218. initPopup() {
  219. // 弹窗
  220. this.overlay = new Overlay({
  221. element: this.$refs.popup, // 弹窗标签,在html里
  222. autoPan: true, // 如果弹窗在底图边缘时,底图会移动
  223. autoPanAnimation: { // 底图移动动画
  224. duration: 250
  225. },
  226. });
  227. this.map = this.baseMap.map;
  228. this.map.addOverlay(this.overlay);
  229. this.mapClick() // 初始化地图成功后,给地图添加点击事件
  230. const dragBox = new DragBox({
  231. condition: platformModifierKeyOnly,
  232. });
  233. this.map.addInteraction(dragBox);
  234. dragBox.on('boxend', (evt) => {
  235. const extent = dragBox.getGeometry().getExtent();
  236. let queryLayer = this.getVisibleLayers();
  237. if (queryLayer.length === 0) return;
  238. queryLayer.forEach((item) => {
  239. let vectorSource = item.layer.getSource();
  240. /*const boxFeatures = vectorSource
  241. .getFeaturesInExtent(extent)
  242. .filter((feature) => feature.getGeometry().intersectsExtent(extent));*/
  243. // console.log(boxFeatures);
  244. })
  245. });
  246. },
  247. mapClick() { // 地图点击事件
  248. // 通过 map.on() 监听,singleclick 是单击的意思。也可以用 click 代替 singleclick。
  249. this.mapCursorKey = this.map.on('singleclick', evt => {
  250. this.currentCoordinate = evt.coordinate; // 获取坐标
  251. this.tabs = [];
  252. let viewResolution = this.map.getView().getResolution();
  253. // 获取可查的图层
  254. let queryLayer = this.getVisibleLayers();
  255. if (queryLayer.length === 0) return;
  256. queryLayer.forEach((item) => {
  257. let url = item.layer.getSource().getFeatureInfoUrl(
  258. this.currentCoordinate,
  259. viewResolution,
  260. 'EPSG:4490',
  261. {
  262. 'INFO_FORMAT': 'application/json', //geoserver支持jsonp才能输出为jsonp的格式
  263. 'FEATURE_COUNT': 50 //点击查询能返回的数量上限
  264. });
  265. axios({url, method: 'get'})
  266. .then(async (res) => {
  267. let {status, data: {features}} = res;
  268. if (status === 200) {
  269. if (features.length === 0) return;
  270. this.properties = features[0].properties;
  271. this.getTreeExpandKeys(this.baseMap.list, item.name);
  272. let labels = this.labels;
  273. if (this.dataport) {
  274. let {
  275. message,
  276. success,
  277. result
  278. } = await getAction(this.dataport, {id: this.properties[this.relfield]});
  279. if (success) {
  280. this.properties = result;
  281. } else {
  282. this.$message.error(message);
  283. return;
  284. }
  285. this.dataport = '';
  286. }
  287. if (labels.length > 0) {
  288. labels.forEach((itemA) => {
  289. itemA.content = this.properties[itemA.name];
  290. });
  291. let tab = {name: item.name, inner: labels};
  292. this.tabs.push({...tab});
  293. setTimeout(() => {
  294. // 设置弹窗位置
  295. // 这里要设置定时器, 不然弹窗首次出现, 底图会跑偏
  296. this.overlay.setPosition(this.currentCoordinate);
  297. }, 0)
  298. }
  299. } else {
  300. console.log('错误');
  301. }
  302. });
  303. })
  304. });
  305. },
  306. getVisibleLayers(layerName) {
  307. let layer = [];
  308. let item = {};
  309. let layers = this.map.getLayers();
  310. let layerCount = layers.getLength();
  311. for (let i = 0; i < layerCount; i++) {
  312. let visible = layers.item(i).get('visible');
  313. let name = layers.item(i).get('alias');
  314. if (visible && name) {
  315. item = {name, 'layer': layers.item(i)}
  316. layer.push(item);
  317. }
  318. }
  319. return layer;
  320. },
  321. }
  322. }
  323. </script>
  324. <style scoped="scoped">
  325. .toolBar {
  326. position: absolute;
  327. top: 0.8em;
  328. left: 5em;
  329. border-radius: 4px;
  330. padding: 0;
  331. margin: 0;
  332. background-color: whitesmoke;
  333. cursor: pointer;
  334. z-index: 1;
  335. box-shadow: 0 0 5px #357ee5;
  336. opacity: 0.9;
  337. }
  338. .nav {
  339. padding-left: 0;
  340. margin-bottom: 0;
  341. list-style: none;
  342. display: flex;
  343. }
  344. .nav-pills > li {
  345. float: left;
  346. }
  347. .nav > li {
  348. position: relative;
  349. display: block;
  350. }
  351. .nav-pills > li + li {
  352. margin-left: 2px;
  353. }
  354. .nav-pills > li > a {
  355. border-radius: 4px;
  356. }
  357. .nav > li > a {
  358. position: relative;
  359. display: block;
  360. padding: 10px 15px;
  361. }
  362. .nav > li > a:hover,
  363. .nav > li > a:focus {
  364. text-decoration: none;
  365. background-color: #eeeeee;
  366. }
  367. a {
  368. color: #337ab7;
  369. text-decoration: none;
  370. }
  371. .nav > li > a > img {
  372. max-width: none;
  373. }
  374. img {
  375. vertical-align: middle;
  376. }
  377. #measureTool, #drawTool {
  378. position: absolute;
  379. top: 52px;
  380. left: 0px;
  381. }
  382. #coordsLocate {
  383. position: absolute;
  384. top: 52px;
  385. left: 0;
  386. }
  387. #resourceCatalog {
  388. position: absolute;
  389. top: 52px;
  390. left: 0;
  391. }
  392. #queryTool {
  393. position: absolute;
  394. top: 52px;
  395. left: 0;
  396. }
  397. </style>