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

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

父组件

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>
相关推荐
猫头_26 分钟前
uni-app 转微信小程序 · 避坑与实战全记录
前端·微信小程序·uni-app
天生我材必有用_吴用29 分钟前
网页接入弹窗客服功能的完整实现(Vue3 + WebSocket预备方案)
前端
海拥35 分钟前
8 Ball Pool:在浏览器里打一局酣畅淋漓的桌球!
前端
Cache技术分享42 分钟前
148. Java Lambda 表达式 - 捕获局部变量
前端·后端
YGY Webgis糕手之路1 小时前
Cesium 快速入门(二)底图更换
前端·经验分享·笔记·vue
神仙别闹1 小时前
基于JSP+MySQL 实现(Web)毕业设计题目收集系统
java·前端·mysql
前端李二牛1 小时前
Web字体使用最佳实践
前端·http
YGY_Webgis糕手之路1 小时前
Cesium 快速入门(六)实体类型介绍
前端·gis·cesium
Jacob02341 小时前
UI 代码不写也行?我用 MCP Server 和 ShadCN 自动生成前端界面
前端·llm·ai编程
爱泡脚的鸡腿1 小时前
Vue第五次笔记
前端·vue.js