index.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <template>
  2. <div ref="containerRef" class="map-container">
  3. <div id="aMap" class="map-container" :style="{ width: width, height: height }"></div>
  4. <!-- 右下工具 -->
  5. <div v-show="mapState.showScale" class="zoom-text">{{ mapState.zoom }}级</div>
  6. <div class="right-tool">
  7. <!-- 快捷缩放 -->
  8. <QuickZoom v-model:zoom="mapState.zoom" @change-step="setMapZoom" />
  9. <div class="flex" style="margin-top: 5px">
  10. <div class="model-btn" @click="switchThreeDimensional">{{ mapState.isThreeDimensional ? '3D' : '2D' }}</div>
  11. <div class="ruler-icon" style="margin-left: 5px" @click="changeScaleControl"></div>
  12. </div>
  13. <!-- 测距工具 -->
  14. <!--<div class="model-btn" @click="toggleRangingTool">-->
  15. <!--{{ isRanging ? '关闭测距' : '开启测距' }}-->
  16. <!--</div>-->
  17. </div>
  18. </div>
  19. </template>
  20. <script setup lang="ts" name="Map">
  21. import QuickZoom from './quickZoom.vue';
  22. import { useAMap } from '@/hooks/AMap/useAMap';
  23. import { useDrawTool } from '@/hooks/AMap/useDrawTool';
  24. import { useRuler } from '@/hooks/AMap/useRuler';
  25. import { getPointInfoList } from '@/api/globalMap';
  26. import { getDictLabel } from '@/utils/dict';
  27. import { PointType } from '@/api/globalMap/type';
  28. import {
  29. getEmergencyExpertDetails,
  30. getEmergencyShelterTypeDetails,
  31. getGasolinestationDetails,
  32. getHospitalDetails,
  33. getMiningcompanyDetails,
  34. getRescueMateriaDetails,
  35. getChemicalcompanyDetails,
  36. getSchoolDetails,
  37. getWaterloggedRoadsDetails,
  38. getShipRealtilmePositionDetails,
  39. getPeratingEenterpriseDetails,getUAVDetails
  40. } from "@/api/globalMap/spatialAnalysis";
  41. import { pointDetailTemplate } from '@/views/globalMap/data/mapData';
  42. interface Props {
  43. activeMap: string;
  44. pointType: PointType[];
  45. }
  46. const containerScale = inject('containerScale');
  47. const props = withDefaults(defineProps<Props>(), {});
  48. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  49. const { point_type } = toRefs<any>(proxy?.useDict('point_type'));
  50. const emits = defineEmits(['update:drawing', 'selectGraphics', 'unSelectGraphics', 'showTextEditBox', 'onDrawCompleted']);
  51. const containerRef = ref();
  52. const width = ref('100%');
  53. const height = ref('100%');
  54. const mapState = reactive({
  55. center: [110.93154257997, 21.669064031332],
  56. zoom: 15,
  57. minZoom: 6,
  58. maxZoom: 20,
  59. isThreeDimensional: false,
  60. // 是否显示比例尺
  61. showScale: true
  62. });
  63. let AMap, map, scale;
  64. // 鼠标绘制工具
  65. const drawTool = useDrawTool();
  66. // 初始化地图
  67. const { getAMap, getMap, switchMap, addMarker, addSearchMarker, clearMarker, getMarkers, getScale, showInfo } = useAMap({
  68. key: '30d3d8448efd68cb0b284549fd41adcf', // 申请好的Web端开发者Key,首次调用 load 时必填
  69. version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  70. pitch: mapState.isThreeDimensional ? 45 : 0,
  71. zoom: mapState.zoom,
  72. center: [mapState.center[0], mapState.center[1]],
  73. dragEnable: true,
  74. scrollWheel: true,
  75. showScale: true,
  76. enableMouseTool: true,
  77. // 加载完成事件
  78. onLoadCompleted: () => {
  79. AMap = getAMap();
  80. map = getMap();
  81. scale = getScale();
  82. if (!['logical', 'vectorgraph'].includes(props.activeMap)) {
  83. switchMap(props.activeMap);
  84. } else {
  85. map.removeLayer();
  86. }
  87. map.on('zoomchange', zoomChangeHandler);
  88. drawTool.initMouseTool({ container: 'aMap', map, AMap });
  89. handleResize();
  90. },
  91. onMarkerClick: (data) => {
  92. // 多点位
  93. if (data.type === '1') {
  94. let path = [];
  95. props.pointType.forEach((item) => {
  96. path.push(item.component);
  97. });
  98. getPointInfoList({
  99. option: path.toString(),
  100. longitude: data.longitude.toString(),
  101. latitude: data.latitude.toString()
  102. }).then((res) => {
  103. const data2 = res.data.list;
  104. let content = document.createElement('div');
  105. content.className = 'point-info';
  106. let table = document.createElement('div');
  107. table.className = 'point-item';
  108. table.innerHTML = '<div>主题</div><div>名称</div>';
  109. content.appendChild(table);
  110. data2.forEach((item) => {
  111. item.longitude = data.longitude;
  112. item.latitude = data.latitude;
  113. const div = document.createElement('div');
  114. div.className = 'point-item';
  115. div.innerHTML = '<div>' + getDictLabel(point_type.value, item.dataType.toString()) + '</div><div>' + item.name + '</div>';
  116. div.addEventListener('click', () => handlePointDetails(item));
  117. content.appendChild(div);
  118. });
  119. showInfo(content, [data.longitude, data.latitude]);
  120. });
  121. } else {
  122. handlePointDetails(data);
  123. }
  124. }
  125. });
  126. const handlePointDetails = (data) => {
  127. let methodList = {
  128. '1': getEmergencyExpertDetails,
  129. '2': getRescueMateriaDetails,
  130. '3': getEmergencyShelterTypeDetails,
  131. '4': getWaterloggedRoadsDetails,
  132. '5': getSchoolDetails,
  133. '6': getHospitalDetails,
  134. '7': getGasolinestationDetails,
  135. '8': getMiningcompanyDetails,
  136. // '9': getChemicalcompanyDetails,
  137. '10': getShipRealtilmePositionDetails,
  138. '11': getChemicalcompanyDetails,
  139. '12': getChemicalcompanyDetails,
  140. '13': getChemicalcompanyDetails,
  141. '14': getChemicalcompanyDetails,
  142. '15': getUAVDetails
  143. };
  144. let method = methodList[data.dataType];
  145. if (!method) return;
  146. method(data.id).then((res) => {
  147. if (!!pointDetailTemplate[data.dataType]) {
  148. let content = document.createElement('div');
  149. content.className = 'point-info';
  150. for (let key in res.rows[0]) {
  151. let keyLabel = !!pointDetailTemplate[data.dataType][key] ? pointDetailTemplate[data.dataType][key] : key;
  152. const div = document.createElement('div');
  153. div.className = 'point-item';
  154. div.innerHTML = '<div>' + keyLabel + '</div><div>' + res.rows[0][key] + '</div>';
  155. content.appendChild(div);
  156. }
  157. showInfo(content, [data.longitude, data.latitude]);
  158. }
  159. });
  160. };
  161. // 监听地图类型变化
  162. watch(
  163. () => props.activeMap,
  164. (value, oldValue) => {
  165. switchMap(props.activeMap);
  166. }
  167. );
  168. // watch(
  169. // () => props.mouseToolState,
  170. // () => {
  171. // if (props.drawing) {
  172. // drawGraphics(props.mouseToolState);
  173. // } else {
  174. // closeDraw();
  175. // }
  176. // },
  177. // {
  178. // deep: true
  179. // }
  180. // );
  181. // 缩放级别变化
  182. const zoomChangeHandler = () => {
  183. mapState.zoom = map.getZoom();
  184. };
  185. // 切换比例尺
  186. const changeScaleControl = () => {
  187. mapState.showScale = !mapState.showScale;
  188. if (mapState.showScale) {
  189. map.addControl(scale);
  190. } else {
  191. map.removeControl(scale);
  192. }
  193. };
  194. // 设置地图层级
  195. const setMapZoom = (value) => {
  196. if (!map) return;
  197. if (value === 1) {
  198. map.setCenter([113.280637, 23.125178]);
  199. map.setZoom(7);
  200. } else if (value === 2) {
  201. map.setCenter([110.93154257997, 21.6690640313328]);
  202. map.setZoom(11);
  203. } else if (value === 3) {
  204. map.setCenter([110.93154257997, 21.669064031332]);
  205. map.setZoom(13);
  206. } else if (value === 4) {
  207. map.setCenter([110.93154257997, 21.669064031332]);
  208. map.setZoom(15);
  209. } else if (value === 5) {
  210. map.setCenter([110.93154257997, 21.669064031332]);
  211. map.setZoom(18);
  212. }
  213. };
  214. // 切换2D、3D
  215. const switchThreeDimensional = () => {
  216. mapState.isThreeDimensional = !mapState.isThreeDimensional;
  217. const pitch = mapState.isThreeDimensional ? 45 : 0;
  218. map.setPitch(pitch);
  219. };
  220. const setCenter = (item) => {
  221. map.setCenter([item.longitude, item.latitude]);
  222. };
  223. defineExpose({ addMarker, addSearchMarker, setCenter, getMarkers, clearMarker, getMap, drawTool });
  224. const handleResize = () => {
  225. const containerWidth = containerRef.value.clientWidth * containerScale().scaleX;
  226. const containerHeight = containerRef.value.clientHeight * containerScale().scaleY;
  227. width.value = containerWidth + 'px';
  228. height.value = containerHeight + 'px';
  229. map.resize();
  230. };
  231. onMounted(() => {
  232. window.addEventListener('resize', handleResize);
  233. });
  234. // 卸载事件
  235. onUnmounted(() => {
  236. if (map) {
  237. map.off('zoomchange', zoomChangeHandler);
  238. }
  239. window.removeEventListener('resize', handleResize);
  240. });
  241. </script>
  242. <style lang="scss" scoped>
  243. @import 'map.scss';
  244. .map-container {
  245. width: 100%;
  246. height: 100%;
  247. position: relative;
  248. overflow: hidden;
  249. .zoom-text {
  250. position: absolute;
  251. bottom: 0;
  252. right: 170px;
  253. color: #eaf3fc;
  254. font-size: 25.73px;
  255. font-family: 'SourceHanSansCN';
  256. }
  257. .right-tool {
  258. position: absolute;
  259. bottom: 50px;
  260. right: 5px;
  261. z-index: 2;
  262. }
  263. .model-btn {
  264. background-color: #04327c;
  265. font-size: 25.73px;
  266. font-family: 'SourceHanSansCN';
  267. border: 1px solid #91cfff;
  268. color: #eaf3fc;
  269. cursor: pointer;
  270. padding: 3px 3px;
  271. border-radius: 5px;
  272. }
  273. .ruler-icon {
  274. width: 42px;
  275. height: 42px;
  276. background: url('@/assets/images/map/ruler.png') no-repeat;
  277. cursor: pointer;
  278. }
  279. :deep(.amap-scalecontrol) {
  280. left: unset !important;
  281. background-color: unset !important;
  282. right: vw(170);
  283. bottom: vw(0) !important;
  284. }
  285. :deep(.amap-scale-text) {
  286. text-align: left !important;
  287. padding-left: 20px;
  288. color: #eaf3fc;
  289. font-size: vw(25.73);
  290. font-family: 'SourceHanSansCN';
  291. }
  292. :deep(.amap-scale-edgeleft),
  293. :deep(.amap-scale-middle),
  294. :deep(.amap-scale-edgeright) {
  295. border: 1px solid #bfe1fc !important;
  296. background: transparent !important;
  297. }
  298. :deep(.amap-logo),
  299. :deep(.amap-copyright) {
  300. display: none !important;
  301. }
  302. /* 自定义测距工具样式 */
  303. :deep(.amap-ranger) {
  304. background-color: #ffffff;
  305. border: 1px solid #888888;
  306. border-radius: 5px;
  307. padding: 5px;
  308. }
  309. :deep(.amap-ranger .amap-toolbar) {
  310. color: #333;
  311. font-size: 12px;
  312. padding: 5px;
  313. }
  314. :deep(.amap-ranger .amap-toolbar button) {
  315. background-color: #022577;
  316. color: #fff;
  317. border: none;
  318. border-radius: 4px;
  319. padding: 5px;
  320. margin-right: 5px;
  321. cursor: pointer;
  322. }
  323. :deep(.amap-ranger .amap-toolbar button:hover) {
  324. background-color: #1a3c75;
  325. }
  326. :deep(.amap-ranger .amap-toolbar .amap-toolbar-text) {
  327. color: #444;
  328. font-size: 14px;
  329. }
  330. :deep(.amap-marker) {
  331. font-size: 16px;
  332. }
  333. }
  334. </style>