高德地图经纬度显示点位及输入位置选择经纬度

根据经纬度展示地图,点击选择经纬度按钮打开弹窗

父组件

xml 复制代码
<template>
  <div>
    <el-row :gutter="24">
      <el-col :span="6">
        <el-form-item label="经纬度" prop="latLng">
          <el-input v-model="latLng" placeholder="请选择经纬度" @clear="clearLatLng"  clearable />
        </el-form-item>
      </el-col>

      <el-col :span="6">
        <el-button type="primary" @click="openChoose">选择经纬度</el-button>
      </el-col>
    </el-row>

    <lat-lng-area ref="latLngArea"></lat-lng-area>

    <lat-lng-choose ref="latLngChoose" @chooseSuccess="chooseSuccess"></lat-lng-choose>
  </div>

</template>

<script setup>

import LatLngChoose from "../../latLngChoose/latLngChoose.vue";
import LatLngArea from "../../latLngChoose/latLngArea.vue";
import {useRoute} from "vue-router";

const route = useRoute()
const emit = defineEmits(['success'])

const latLngChoose = ref(null)
const latLngArea = ref(null)

const props = defineProps({
  latLng: {
    type: String,
    default: ''
  },
})

const latLng = ref('')

//经纬度
function clearLatLng(){
  emit('success', latLng.value)
}

const chooseSuccess = (getLatLng) =>{
  latLng.value = getLatLng
  emit('success', latLng.value)
}
//经纬度弹窗
const openChoose = ()=>{
  nextTick(()=>{
    if(latLngChoose.value){
      latLngChoose.value.show(latLng.value)
    }
  })
}

function changeLatLng(value){
  console.log(value)
  if(value){
    latLng.value = value
    nextTick(()=>{
      if(latLngArea.value){
        latLngArea.value.show(latLng.value)
      }
    })
  }else{
    latLng.value = value
    if(latLngArea.value){
      latLngArea.value.resetMapState()
    }
  }

}

watch(() => props.latLng, value => changeLatLng(value))
</script>

<style scoped>

</style>

展示经纬度位置

xml 复制代码
<template>
  <div>
    <div id="map_container" ref="map" style="height: 500px"></div>
  </div>
</template>

<script setup>
import { ref, nextTick } from 'vue'

const map = ref(null)
//地图实例
const mapInstance = ref(null)

const poiPickerInstance = ref(null)
const markerInstance = ref(null)
const infoWindowInstance = ref(null)


let initialLatLng = ''

const show = (value)=>{
  initialLatLng  = value
  resetMapState()

  makeLat()
}

// 统一清理函数
const resetMapState = () => {
  if (poiPickerInstance.value) {
    poiPickerInstance.value.destroy()
    poiPickerInstance.value = null
  }
  clearMapOverlays()
}

// 清理函数
const clearMapOverlays = () => {
  // 移除标记
  if (markerInstance.value) {
    markerInstance.value.setMap(null) // 关键:从地图移除
    markerInstance.value = null
  }

  // 关闭信息窗口
  if (infoWindowInstance.value) {
    infoWindowInstance.value.close() // 关键:关闭窗口
    infoWindowInstance.value = null
  }
}

const makeLat = () => {
  nextTick(() => {

    AMapUI.loadUI(['misc/PoiPicker'], function(PoiPicker) {
      poiPickerInstance.value = new PoiPicker({

        placeSearchOptions: {
          map: mapInstance.value,
          pageSize: 10
        },
      });
      poiPickerReady(poiPickerInstance.value);
    })

    function poiPickerReady(poiPicker) {

      window.poiPicker=null
      window.poiPicker = poiPicker;
      markerInstance.value =null
          markerInstance.value = new AMap.Marker();
      infoWindowInstance.value = null
          infoWindowInstance.value = new AMap.InfoWindow({
        offset: new AMap.Pixel(0, -20),
        isCustom: true,  // 使用自定义窗体
        autoMove: true,  // 是否自动调整窗体到视野内
      });

      if (initialLatLng) {
        const position = new AMap.LngLat(...initialLatLng.split(',').map(Number));
        mapInstance.value.setCenter(position);
        markerInstance.value.setMap(mapInstance.value);
        markerInstance.value.setPosition(position);
        // 使用地理编码服务获取地址信息
        const geocoder = new AMap.Geocoder();
        geocoder.getAddress(position, (status, result) => {
          if (status === 'complete' && result.info === 'OK') {
            const address = result.regeocode;
            infoWindowInstance.value.setContent(`
              <div style="
                padding: 12px 16px;
                width: 280px;
                background: white;
                border-radius: 8px;
                box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
                transition: all 0.3s ease;
              ">
                <h4 style="
                  margin: 0 0 6px 0;
                  padding-bottom: 4px;
                  border-bottom: 1px solid #eee;
                  color: #333;
                  font-size: 15px;
                ">📌 位置信息</h4>
                <div style="
                  font-size: 13px;
                  line-height: 2;
                  color: #666;
                ">
                  <div><b>经纬度:</b>${initialLatLng}</div>
                  <div><b>详细地址:</b>${address.formattedAddress}</div>
                </div>
              </div>
            `);
            infoWindowInstance.value.setMap(mapInstance.value);
            infoWindowInstance.value.setPosition(position);
            infoWindowInstance.value.open(mapInstance.value, position);
          }
        });

      }
    }
  });
}

onMounted(()=>{
  // 创建地图实例
  mapInstance.value= new AMap.Map(map.value, {
    zoom: 11,
    center: [120.30548699999986, 31.86],
  });
})

defineExpose({
  show,resetMapState
})
</script>





<style>
/* 移除高德地图相关元素 */
.dg, .main, .a{
  display: none;
}
.amap-logo, .amap-copyright {
  display: none !important;
}
</style>
<style scoped>
html,
body,
#container {
  width: 100%;
  height: 100%;
  margin: 0px;
  font-size: 13px;
}
.pickerBox {
  position: absolute;
  z-index: 9999;
  top: 30px; /* 调整位置避免重叠 */
  right: 20px;
  width: 280px;
}

/* 添加深度选择器处理第三方样式 */
:deep(.amap-layers) {
  z-index: 1;
}
:deep(.amap-markers) {
  z-index: 999;
}

#pickerInput {
  width: 200px;
  padding: 5px 5px;
}

.poiInfo {
  background: #fff;
}

.amap_lib_placeSearch .poibox.highlight {
  background-color: #CAE1FF;
}

.amap_lib_placeSearch .poi-more {
  display: none!important;
}
</style>

选择地点

css 复制代码
<script setup>
import { ref, nextTick } from 'vue'

const visible = ref(false)
const getLatLng = ref('')

let initialLatLng = ''

const emits = defineEmits(['chooseSuccess'])

let mapObj = null

const show = (latLng)=>{
  visible.value = true
  if(latLng) initialLatLng  = latLng
  makeLat()
}

// 关闭对话框
const cancel = () => {
  visible.value = false
}

// // 关闭对话框
const submitForm = () => {
  if(![null,undefined,''].includes(getLatLng.value)){
    emits('chooseSuccess',getLatLng.value)
  }

  visible.value = false
}

const makeLat = () => {
  nextTick(() => {
    var map = new AMap.Map("container", {
      zoom: 11,
      center: initialLatLng ? initialLatLng.split(',') : ''
    });

    AMapUI.loadUI(['misc/PoiPicker'], function(PoiPicker) {

      var poiPicker = new PoiPicker({
        input: 'pickerInput',
        placeSearchOptions: {
          map: map,
          pageSize: 10
        },
      });
      poiPickerReady(poiPicker);
    })
    mapObj = map

    function poiPickerReady(poiPicker) {
      window.poiPicker = poiPicker;

      var marker = new AMap.Marker();

      var infoWindow = new AMap.InfoWindow({
        offset: new AMap.Pixel(0, -20),
        isCustom: true,  // 使用自定义窗体
        autoMove: true,  // 是否自动调整窗体到视野内
      });

      if (initialLatLng) {
        const position = new AMap.LngLat(...initialLatLng.split(',').map(Number));
        marker.setMap(map);
        marker.setPosition(position);
        // 使用地理编码服务获取地址信息
        const geocoder = new AMap.Geocoder();
        geocoder.getAddress(position, (status, result) => {
          if (status === 'complete' && result.info === 'OK') {
            const address = result.regeocode;
            infoWindow.setContent(`
              <div style="
                padding: 12px 16px;
                width: 280px;
                background: white;
                border-radius: 8px;
                box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
                transition: all 0.3s ease;
              ">
                <h4 style="
                  margin: 0 0 6px 0;
                  padding-bottom: 4px;
                  border-bottom: 1px solid #eee;
                  color: #333;
                  font-size: 15px;
                ">📌 位置信息</h4>
                <div style="
                  font-size: 13px;
                  line-height: 2;
                  color: #666;
                ">
                  <div><b>经纬度:</b>${initialLatLng}</div>
                  <div><b>详细地址:</b>${address.formattedAddress}</div>
                </div>
              </div>
            `);
            infoWindow.setMap(map);
            infoWindow.setPosition(position);
            infoWindow.open(map, position);
          }
        });

        getLatLng.value = initialLatLng;
      }

      //选取了某个POI
      poiPicker.on('poiPicked', function(poiResult) {
        var source = poiResult.source,
            poi = poiResult.item,
            info =
            {
              name:poi.name,
              location:poi.location.toString(),
              address:poi.address
            }


        if(![null,undefined,''].includes(poi.location)){
          getLatLng.value = poi.location.toString()
        }

        marker.setMap(map);
        infoWindow.setMap(map);

        marker.setPosition(poi.location);
        infoWindow.setPosition(poi.location);

        infoWindow.setContent(`
          <div style="
            padding: 12px 16px;
            width: 280px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
            transition: all 0.3s ease;
          ">
            <h4 style="
              margin: 0 0 6px 0;
              padding-bottom: 4px;
              border-bottom: 1px solid #eee;
              color: #333;
              font-size: 15px;
            ">📌 位置信息</h4>
            <div style="
              font-size: 13px;
              line-height: 2;
              color: #666;
            ">
              <div style="
              font-size: 13px;
              line-height: 2;
              color: #666;
            "><b>地点名称:</b>${info.name}</div>
              <div style="
              font-size: 13px;
              line-height: 2;
              color: #666;
            "><b>经纬度:</b>${info.location}</div>
              <div style="
              font-size: 13px;
              line-height: 2;
              color: #666;
            "><b>详细地址信息:</b>${info.address}</div>
            </div>
          </div>
        `);
        infoWindow.open(map, marker.getPosition());

        mapObj.setCenter(marker.getPosition());
      });
    }
  });
}

// 暴露方法给父组件使用
defineExpose({
  show
})
</script>



<template>
  <div>
    <el-dialog :title="'选择经纬度'" v-model="visible" width="900px" append-to-body custom-class="company-dialog" destroy-on-close @close="cancel">
      <!-- 修改搜索框,添加 id -->
      <div id="pickerBox">
        <input id="pickerInput" placeholder="输入关键字选取地点" />
        <div id="poiInfo"></div>
      </div>

      <!-- 原有的地图容器 -->
      <div id="container" style="height: 400px"></div>
      <div class="input-card">
        <label style='color:grey'>请搜索后选择具体位置以获取准确经纬度</label>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancel">取 消</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<style>
/* 移除高德地图相关元素 */
.dg, .main, .a{
  display: none;
}
.amap-logo, .amap-copyright {
  display: none !important;
}
</style>
<style scoped>
html,
body,
#container {
  width: 100%;
  height: 100%;
  margin: 0px;
  font-size: 13px;
}

#pickerBox {
  position: absolute;
  z-index: 9999;
  top: 50px;
  right: 30px;
  width: 300px;
}

#pickerInput {
  width: 200px;
  padding: 5px 5px;
}

#poiInfo {
  background: #fff;
}

.amap_lib_placeSearch .poibox.highlight {
  background-color: #CAE1FF;
}

.amap_lib_placeSearch .poi-more {
  display: none!important;
}
</style>
相关推荐
程序员小富2 分钟前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇2 分钟前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇2 分钟前
React中的forwardRef
前端·react.js·面试
槑有老呆10 分钟前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
风骏时光牛马13 分钟前
Verilog开发常见问题汇总解析
前端
子兮曰15 分钟前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端
weedsfly19 分钟前
语法糖褪去之后——Babel 转译产物中的 JavaScript 本貌
前端·javascript
JustHappy21 分钟前
「软件设计思想杂谈🤔」“切图仔”也能懂编译原理?框架源码也许没那么难。聊聊 Vue 的编译(上)
前端·javascript·vue.js
禅思院35 分钟前
路由性能高可用架构实战方案
前端·架构·前端框架