首先安装地图插件
cnpm i @amap/amap-jsapi-loader --save
封装地图子组件
<template><el-dialogtitle="选择地点"width="740px"class="select-map-dialog"v-model="dialogShow":close-on-click-modal="false":modal-orgend-to-body="false":append-to-body="true"@close="cancel"><div class="amap-box"><el-input clearable id="keyword" v-model="tipInput" placeholder="关键词搜索" :prefix-icon="Search"></el-input><div id="custom-amap"></div><div class="info-list" v-if="address"><div class="info-item">已选择地点:{{ address }}</div><div class="info-item">地点经纬度:{{ point }}</div></div></div><template #footer><div class="dialog-footer"><el-button type="primary" @click="handelSave">确定</el-button><el-button @click="cancel">取消</el-button></div></template></el-dialog>
</template><script setup>
import { ref, onUnmounted, watch, computed, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import AMapLoader from '@amap/amap-jsapi-loader'
import { Search } from '@element-plus/icons-vue'const map = ref(null)
const address = ref('')
const point = ref([]) const marker = ref('')
const geocoder = ref('') const tipInput = ref('')
const autoComplete = ref(null)
const placeSearch = ref(null)const props = defineProps({defaultAddress: {type: String,default: ''},defaultPoint: {type: Array,default:[]},isShow: {type: Boolean,default: false}
})const emits = defineEmits(['update:isShow', 'getPosition'])
const dialogShow = computed({get: () => props.isShow,set: (value) => {emits('update:isShow', value)}
})watch(() => dialogShow,async () => {setTimeout(()=>{initMap()},100)},{ deep: true },{ immediate: true }
)
const initMap = () => {AMapLoader.load({key: '你的key', version: '2.0', plugins: ['AMap.ToolBar','AMap.Scale','AMap.HawkEye','AMap.MapType','AMap.Geolocation','AMap.AutoComplete','AMap.PlaceSearch','AMap.Geocoder'] }).then((AMap) => {const tempCenter = props.defaultPoint[0]? props.defaultPoint: [118.784136, 32.041806]map.value = new AMap.Map('custom-amap', {viewMode: '2D', zoom: 12, showLabel: true, resizeEnable: true,center: tempCenter })if (props.defaultPoint.length > 0) {address.value = props.defaultAddresspoint.value = props.defaultPointaddMarker()}map.value.on('click', clickMapHandler)map.value.addControl(new AMap.Scale())map.value.addControl(new AMap.ToolBar())map.value.addControl(new AMap.HawkEye())map.value.addControl(new AMap.MapType())map.value.addControl(new AMap.Geolocation())autoComplete.value = new AMap.AutoComplete({input: 'keyword' })placeSearch.value = new AMap.PlaceSearch({map: map.value})autoComplete.value.on('select', selectHandler)placeSearch.value.on('markerClick', clickMarkerHandler)}).catch((e) => {console.log(e)})
}const clickMapHandler = (e) => {const lng = e.lnglat.lngconst lat = e.lnglat.latpoint.value = [lng, lat]addMarker()getAddress()
}
const addMarker = () => {if (marker.value) {marker.value.setMap(null)marker.value = null}marker.value = new AMap.Marker({position: point.value, offset: new AMap.Pixel(-13, -30), icon: new AMap.Icon({image:'//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',size: new AMap.Size(30, 40), imageSize: new AMap.Size(30, 40)})})marker.value.setMap(map.value)
}
const getAddress = () => {geocoder.value = new AMap.Geocoder()geocoder.value.getAddress(point.value, (status, result) => {if (status === 'complete' && result.info === 'OK') {if (result && result.regeocode) {address.value = result.regeocode.formattedAddress}}})
}
const selectHandler = (e) => {placeSearch.value.setCity(e.poi.adcode)placeSearch.value.search(e.poi.name)
}
const clickMarkerHandler = (e) => {point.value = [e.data.location.lng, e.data.location.lat]getAddress()
}
const handelSave = () => {if (address.value && point.value.length && point.value.length > 0) {const infoObj = {address: address.value,point: point.value}tipInput.value = ''emits('getPosition', infoObj)} else {ElMessage.error('请选择地址获取经纬度')}
}
const cancel = () => {tipInput.value = ''
}onUnmounted(() => {map.value && map.value.destroy()
})
</script><style lang="scss" scoped>
.amap-box {padding: 5px 0 0;#custom-amap {width: 700px;height: 400px;margin-top: 10px;border: 1px solid #ccc;}.input-with {width: 580px;z-index: 1;}.address {color: #373737;}.info-list {padding: 5px 5px 0;line-height: 24px;}
}
</style><style lang="scss">
.select-map-dialog {.el-dialog__body {padding-top: 3px;padding-bottom: 3px;}
}
.amap-sug-result {z-index: 2024;
}
</style>
父组件引用子组件
<amap :isShow="amapVisible" @getPosition="getPosition" />const getPosition = (infoObj) => {amapVisible.value = false
}