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

父组件
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>