map.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <template>
  2. <div>
  3. <el-dialog title="地图选点" v-model="isShowDialog" width="900px" append-to-body>
  4. <div class="map-container">
  5. <div class="coordinate-search">
  6. <el-input v-model="lng" placeholder="经度" />
  7. <div>-</div>
  8. <el-input v-model="lat" placeholder="纬度" />
  9. <el-button @click="searchByCoordinate" type="primary">搜索</el-button>
  10. </div>
  11. <div class="map" ref="mapContainer"></div>
  12. <!-- 地址解析结果 -->
  13. <div class="address-result" v-if="address">
  14. 解析到地址:{{ address }}
  15. <el-button @click="confirmAddress" style="margin-left: 10px;" type="success">确认地址</el-button>
  16. </div>
  17. </div>
  18. </el-dialog>
  19. </div>
  20. </template>
  21. <script lang="ts" setup>
  22. import { defineEmits, defineExpose, nextTick, ref } from 'vue';
  23. const mapContainer = ref<HTMLElement | null>(null);
  24. const address = ref('');
  25. const lng = ref('');
  26. const lat = ref('');
  27. const isShowDialog = ref(false);
  28. const marker = ref<BMapGL.Marker | null>(null);
  29. let map: BMapGL.Map | null = null;
  30. const openDialog = () => {
  31. isShowDialog.value = true;
  32. nextTick(() => {
  33. map = new BMapGL.Map(mapContainer.value!);
  34. map.centerAndZoom("沈阳市", 10);
  35. map.enableScrollWheelZoom(true);
  36. searchByCoordinate();
  37. map.addEventListener("click", (e: any) => {
  38. lng.value = e.latlng.lng.toFixed(5);
  39. lat.value = e.latlng.lat.toFixed(5);
  40. setMarker(lng.value, lat.value);
  41. setAddressByCoordinate(lng.value, lat.value);
  42. });
  43. });
  44. };
  45. const confirmAddress = () => {
  46. isShowDialog.value = false;
  47. emit('updateMap', { lng: lng.value, lat: lat.value });
  48. };
  49. const setMarker = (lng: string, lat: string) => {
  50. // 删除之前的标记
  51. if (marker.value) {
  52. map?.removeOverlay(marker.value);
  53. }
  54. // 创建新的标记
  55. const point = new BMapGL.Point(lng, lat);
  56. marker.value = new BMapGL.Marker(point);
  57. map?.addOverlay(marker.value);
  58. // 移动地图中心到选点位置
  59. map?.panTo(point);
  60. };
  61. const setAddressByCoordinate = (lng: string | number, lat: string | number) => {
  62. const point = new BMapGL.Point(lng, lat);
  63. const geocoder = new BMapGL.Geocoder();
  64. geocoder.getLocation(point, (result: any) => {
  65. if (result) {
  66. const formattedAddress = result.address;
  67. address.value = formattedAddress;
  68. }
  69. });
  70. };
  71. const searchByCoordinate = () => {
  72. if (lng.value && lat.value) {
  73. setMarker(lng.value, lat.value);
  74. setAddressByCoordinate(lng.value, lat.value);
  75. }
  76. };
  77. const emit = defineEmits(['updateMap']);
  78. defineExpose({ openDialog });
  79. </script>
  80. <style scoped>
  81. .map-container {
  82. display: flex;
  83. flex-direction: column;
  84. align-items: center;
  85. }
  86. .map {
  87. width: 100%;
  88. height: 50vh;
  89. }
  90. .coordinate-search {
  91. display: flex;
  92. margin-bottom: 20px;
  93. }
  94. .coordinate-search > div {
  95. margin-right: 10px;
  96. }
  97. .coordinate-search input {
  98. margin-right: 10px;
  99. width: 100px;
  100. }
  101. .address-result {
  102. margin-top: 20px;
  103. }
  104. </style>