f109992bc9f6dfc25c4f8ef41aaeda6dccf82d28.svn-base 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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. // 点类型服务数据不全,需要再次查询
  274. if (this.dataport) {
  275. let {
  276. message,
  277. success,
  278. result
  279. } = await getAction(this.dataport, {id: this.properties[this.relfield]});
  280. if (success) {
  281. this.properties = result;
  282. } else {
  283. this.$message.error(message);
  284. return;
  285. }
  286. this.dataport = '';
  287. }
  288. // 弹窗内容(详细列表形式)
  289. if (labels.length > 0) {
  290. labels.forEach((itemA) => {
  291. itemA.content = this.properties[itemA.name];
  292. });
  293. let tab = {name: item.name, inner: labels};
  294. this.tabs.push({...tab});
  295. setTimeout(() => {
  296. // 设置弹窗位置
  297. // 这里要设置定时器, 不然弹窗首次出现, 底图会跑偏
  298. this.overlay.setPosition(this.currentCoordinate);
  299. }, 0)
  300. }
  301. } else {
  302. console.log('错误');
  303. }
  304. });
  305. })
  306. });
  307. },
  308. getVisibleLayers(layerName) {
  309. let layer = [];
  310. let item = {};
  311. let layers = this.map.getLayers();
  312. let layerCount = layers.getLength();
  313. for (let i = 0; i < layerCount; i++) {
  314. let visible = layers.item(i).get('visible');
  315. let name = layers.item(i).get('alias');
  316. if (visible && name) {
  317. item = {name, 'layer': layers.item(i)}
  318. layer.push(item);
  319. }
  320. }
  321. return layer;
  322. },
  323. }
  324. }
  325. </script>
  326. <style scoped="scoped">
  327. .toolBar {
  328. position: absolute;
  329. top: 0.8em;
  330. left: 5em;
  331. border-radius: 4px;
  332. padding: 0;
  333. margin: 0;
  334. background-color: whitesmoke;
  335. cursor: pointer;
  336. z-index: 1;
  337. box-shadow: 0 0 5px #357ee5;
  338. opacity: 0.9;
  339. }
  340. .nav {
  341. padding-left: 0;
  342. margin-bottom: 0;
  343. list-style: none;
  344. display: flex;
  345. }
  346. .nav-pills > li {
  347. float: left;
  348. }
  349. .nav > li {
  350. position: relative;
  351. display: block;
  352. }
  353. .nav-pills > li + li {
  354. margin-left: 2px;
  355. }
  356. .nav-pills > li > a {
  357. border-radius: 4px;
  358. }
  359. .nav > li > a {
  360. position: relative;
  361. display: block;
  362. padding: 10px 15px;
  363. }
  364. .nav > li > a:hover,
  365. .nav > li > a:focus {
  366. text-decoration: none;
  367. background-color: #eeeeee;
  368. }
  369. a {
  370. color: #337ab7;
  371. text-decoration: none;
  372. }
  373. .nav > li > a > img {
  374. max-width: none;
  375. }
  376. img {
  377. vertical-align: middle;
  378. }
  379. #measureTool, #drawTool {
  380. position: absolute;
  381. top: 52px;
  382. left: 0px;
  383. }
  384. #coordsLocate {
  385. position: absolute;
  386. top: 52px;
  387. left: 0;
  388. }
  389. #resourceCatalog {
  390. position: absolute;
  391. top: 52px;
  392. left: 0;
  393. }
  394. #queryTool {
  395. position: absolute;
  396. top: 52px;
  397. left: 0;
  398. }
  399. </style>