1、准备工作
需要在 高德开发平台 申请自己的 key 和 密钥
这里的 Key 名称大家可以随意填写
申请完之后我们得到 key 和 密钥
vue中使用需要安装**@amap/amap-jsapi-loader --save** 官方文档
javascript">npm i @amap/amap-jsapi-loader --save
2、代码实现
首先我们需要三个文件,一个 index.vue 一个用来存放省市区的 index.js 文件
一个 map.vue 地图组件
index.vue 代码
<template>
<el-form :model="form" ref="formRef" class="box-from" label-width="95px" label-position="right">
<el-form-item label="省市区">
<el-select v-model="form.province" style="width: 180px;" placeholder="请选择省份" clearable @change="provinceChange"
@clear="provinceClear">
<el-option v-for="item in province" :key="item.code" :label="item.value" :value="item.value" />
</el-select>
<el-select v-model="form.city" style="width: 180px; margin-left: 5px;" placeholder="请选择市" clearable
@change="cityChange" :disabled="form.province === ''" @clear="cityClear">
<el-option v-for="item in city" :key="item.code" :label="item.value" :value="item.value" />
</el-select>
<el-select v-model="form.area" style="width: 180px; margin-left: 5px;" placeholder="请选择区" clearable
:disabled="form.city === ''">
<el-option v-for="item in area" :key="item.code" :label="item.value" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="详细地址">
<el-input style="width: 500px;" type="textarea" v-model="form.address" placeholder="请输入详细地址"
clearable></el-input>
<el-button @click="addressMap" style="margin-left: 5px;">地图跳转</el-button>
</el-form-item>
<el-form-item label="地图选择">
<Map :addressClick="addressClick" ref="mapRef"></Map>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { reactive, ref, toRefs, onMounted } from 'vue';
import { provinceData } from './index'
const state = reactive({
// 表单
province: provinceData,
city: [] as any,
area: [] as any,
form: {
province: '',
city: '',
area: '',
address: ''
},
})
const { form, province, city, area } = toRefs(state)
const mapRef = ref('') as any
onMounted(() => {
// 这里传后台获取的经纬度
mapRef.value.fixed(100.179253, 27.096143)
})
// 省份
function provinceChange(value: any) {
state.province.forEach(item => {
if (item.value === value) {
state.city = item.children
}
})
}
// 市
function cityChange(value: any) {
state.province.forEach(item => {
if (item.value === state.form.province) {
item.children.forEach(text => {
if (text.value === value) {
state.area = text.children
}
})
}
})
}
// 省清空
function provinceClear() {
state.form.city = ""
state.form.area = ""
}
// 市清空
function cityClear() {
state.form.area = ""
}
// 详细地址跳转地图
function addressMap() {
mapRef.value.toGetCoordinate(state.form.address)
}
// 地图选位置
// 把获取的信息同步到三级联动
function addressClick(item: any, lng: any, lat: any) {
if (item.regeocode.address***ponent.city === '') {
state.form.city = item.regeocode.address***ponent.province
} else {
state.form.city = item.regeocode.address***ponent.city
}
state.form.province = item.regeocode.address***ponent.province
state.form.area = item.regeocode.address***ponent.district
state.form.address = item.regeocode.formattedAddress
state.province.forEach(item => {
if (item.value === state.form.province) {
state.city = item.children
item.children.forEach(text => {
if (text.value === state.form.city) {
state.area = text.children
}
})
}
})
}
</script>
<style lang="scss" scoped></style>
map.vue 代码
<template>
<div style="width: 100%;">
<div id="container" class="map"></div>
<div class="search-box">
<el-select v-model="address" clearable placeholder="请输入关键词" style="width: 400px;" :remote-method="remoteMethod"
filterable remote @change="currentSelect" class="one-text" size="default">
<el-option v-for="(item, index) in areaList" :key="index" :label="item.district + item.name"
:value="item.district + item.name">
<span>{{ item.district }}</span> <span>{{ item.name }}</span>
</el-option>
</el-select>
</div>
</div>
</template>
<script setup>
import { reactive, ref, toRefs, onMounted, nextTick, defineProps } from 'vue';
import AMapLoader from "@amap/amap-jsapi-loader";
const props = defineProps({
addressClick: Function,
})
onMounted(() => {
window._AMapSecurityConfig = {
securityJsCode: '这里放key的安全密钥',
}
initMap()
})
const state = reactive({
map: null,
placeSearch: null,
auto***plete: null,
marker: null,
form: {
address: '',
lng: '',
lat: '',
},
areaList: [],
address: ''
})
const { areaList, address } = toRefs(state)
function initMap(arr) {
AMapLoader.load({
key: "这里放你申请的key",
version: "2.0",
plugins: ["AMap.ToolBar", "AMap.ControlBar", 'AMap.Auto***plete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.Marker'],
}).then((AMap) => {
state.map = new AMap.Map('container', {
viewMode: "3D", // 是否为3D地图模式
zoom: 15,
center: arr,
resizeEnable: true
});
// 地图放大缩小插件
let toolBar = new AMap.ToolBar({
position: {
top: '120px',
right: '51px'
}
})
// 3D地图插件
let controlBar = new AMap.ControlBar({
position: {
top: '20px',
right: '20px',
},
});
state.geoCoder = new AMap.Geocoder({
city: '010', //城市设为北京,默认:“全国”
radius: 1000 //范围,默认:500
})
// 正向地理编码
state.geocoder = new AMap.Geocoder({
city: state.address
})
state.auto***plete = new AMap.Auto***plete({ city: '全国' });
state.map.on('click', (e) => { // 点击地图事件
if (!e && !e.lnglat) {
return
}
state.form.lng = e.lnglat.lng
state.form.lat = e.lnglat.lat
removeMarker() // 先删除地图上标记点
setMapMarker() // 在添加新的标记点
})
state.map.addControl(toolBar); // 添加右上角的放大缩小
state.map.addControl(controlBar); // 添加右上角的放大缩小
}).catch((e) => {
console.error(e); //加载错误提示
}).finally(() => {
removeMarker()
setMapMarker()
})
}
function setMapMarker() {
if (state.form.lng == '' && state.form.lat == '') {
return
}
state.map.setFitView()
state.marker = new AMap.Marker({
map: state.map,
position: [state.form.lng, state.form.lat],
})
toGetAddress()
state.map.setFitView()
state.map.add(state.marker)
}
function removeMarker() {
if (state.marker) {
state.map.remove(state.marker)
}
}
function toGetAddress() {
let lnglat = [state.form.lng, state.form.lat]
state.geoCoder.getAddress(lnglat, (status, result) => {
if (status === '***plete' && result.regeocode) {
props.addressClick(result, state.form.lng, state.form.lat) // 返回位置信息以及经纬度
}
})
}
function remoteMethod(query) {
if (query !== '') {
setTimeout(() => {
state.auto***plete.search(query, (status, result) => {
state.areaList = result.tips
})
}, 500)
} else {
state.areaList = []
}
}
function currentSelect(val) {
if (!val) {
return
}
toGetCoordinate(val)
}
function toGetCoordinate(address) {
state.geocoder.getLocation(address, function (status, result) {
if (status === '***plete' && result.info === 'OK') {
initMap([result.geocodes[0].location.lng, result.geocodes[0].location.lat])
state.form.lng = result.geocodes[0].location.lng
state.form.lat = result.geocodes[0].location.lat
state.form.address = result.geocodes[0].formattedAddress
}
})
nextTick(function () {
removeMarker()
setMapMarker()
})
}
function fixed(lng, lat) {
initMap([lng, lat])
state.form.lng = lng
state.form.lat = lat
}
// 暴露方法
defineExpose({
fixed,
toGetCoordinate
});
</script>
<style scoped lang="scss">
.map {
width: 100%;
height: 400px;
}
.search-box {
position: absolute;
z-index: 9;
top: 20px;
left: 20px;
::v-deep(.el-select) {
width: 320px;
border-radius: 50px;
overflow: hidden;
.el-input__wrapper {
border-radius: 50px;
}
}
}
</style>
index.js 代码
这里我以文件的形式上传了,大家直接下载即可 省市区三级联动index.js文件
效果展示
补充
因为高德地图的搜索每天有限制,可能导致地图上面的搜索无法使用
但是
可以在详细地址那里填写地址信息点击后面按钮跳转地图 (注意:既然是详细地址建议跳转时添加上省市区)
替换自己的key和密钥可以直接使用,如有问题可以私信。
如果对你有帮助麻烦点个赞咯~