实现效果图:
1.安装高德地图插件
npm i @amap/amap-jsapi-loader --save-d
2.template模板部分 dialogWrap是自己封装的弹窗组件(根据el-dialog封装的组件)
<dialogWrap :visible.sync="show_"
width="800px"
top="10vh"
title="地址识别"
@confirm="getAddress">
<div class='map-wrap'>
<div id="container"></div>
<div class="search-wrap">
<!-- 搜索框 -->
<div class="search">
<el-input placeholder="请输入内容"
v-model="address"
class="input-with-select"
clearable>
<!-- @input="handleSearch" -->
<el-button slot="append"
icon="el-icon-search"
@click="handleSearch"></el-button>
</el-input>
</div>
<!-- 检索结果 -->
<div v-show="showResultFlag"
class="search-result">
<div v-for="(item, index) in searchResult"
class="item"
:key="index"
@click="reverseeocoding(item.location,item.name)">
<i class="el-icon-search fl mgr10" />
<div style="overflow:hidden;">
<div class="title">{{ item.name }}</div>
<span class="address ellipsis">{{ item.district+item.address }}</span>
</div>
</div>
</div>
</div>
</div>
</dialogWrap>
3.js实现逻辑部分
<script>
import dialogWrap from "../dialog/dialogWrap";
import AMapLoader from "@amap/amap-jsapi-loader";
window._AMapSecurityConfig = {
securityJsCode: "自己申请的高德的安全秘钥",
};
const defaultInfo = {
addressAll: '', //详细地址
address: '', //搜索栏的title | 点击地图的街道号
province: '', // 省
city: '', // 市
district: '', // 区
street: '' // 街道
}
export default {
props: {
emitName: String,
show: {
type: Boolean,
default: false,
},
// 是否只显示到街道
isToStreet: {
type: Boolean,
default: false,
}
},
components: {
dialogWrap,
},
name: 'Map',
data () {
return {
AMap: null,
map: null,
zoom: 15,//地图放大缩小的值
address: '',//搜索地址
searchResult: [],//自动匹配地址结果
showResultFlag: false,
selectInfo: Object.assign({}, defaultInfo),
showInfo: false,
lngLat: '',
location: '',
}
},
computed: {
show_: {
get () {
return this.show
},
set (newVal) {
this.$emit('update:show', newVal)
},
},
},
watch: {
show_ (v) {
if (v) {
this.address = ''
this.showResultFlag = false
this.selectInfo = this.$options.data().selectInfo
this.initMap()
}
}
},
methods: {
initMap () {
AMapLoader.load({
key: "自己申请的高德的Web端开发者Key", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [
"AMap.AutoComplete",
"AMap.PlaceSearch",
"AMap.Geocoder",
], // 需要使用的的插件列表
})
.then((AMap) => {
this.AMap = AMap
this.map = new AMap.Map("container", {
//设置地图容器id
zoom: 10, //初始化地图级别
center: [121.473667, 31.230525], //初始化地图中心点位置
});
this.auto = new AMap.AutoComplete(this.autoOptions);
this.placeSearch = new AMap.PlaceSearch({
map: this.map,
}); //构造地点查询类
this.map.on("click", (e) => {
this.showResultFlag = false
this.reverseeocoding(e.lnglat)
});
//添加固定点标记
let marker1 = new AMap.Marker({
position: new AMap.LngLat(121.473667, 31.230525), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
});
//添加点标记
this.map.add(marker1);
})
.catch((e) => {
console.log(e);
});
},
submit () {
this.showInfo = false
this.show_ = false
top.window.$bus.$emit(`get-address-map-data${this.emitName ? '-' + this.emitName : ''}`, JSON.parse(JSON.stringify(this.selectInfo)))
},
handleSearch () {
let self = this
if (this.address != null) {
this.auto.search(this.address, function (status, res) {
console.log(status, res);
// 查询成功时,res返回对应匹配的POI信息
if (res && res.tips) {
self.searchResult = [...res.tips]
if (self.searchResult.length > 0) {
self.showResultFlag = true
} else {
self.showResultFlag = false
}
} else {
self.showResultFlag = false
}
});
this.map.setZoom(16, true, 1);
}
},
/** 逆地址解析
* @param {Object} point 经纬度
* @param {String} title 搜索栏下拉数据展示的title名称
*/
reverseeocoding (point, title) {
console.log(point);
this.map.clearMap() //清除地图上所有覆盖物point
let marker = new this.AMap.Marker({
position: new this.AMap.LngLat(point.lng, point.lat),
});
this.map.add(marker);//添加点标记
// key是高德"web服务"的key
let params = {
key: '高德"web服务"的key', //!!!一定要申请的是“web服务”的key哈 不然会提示你无效的
location: point.lng + "," + point.lat,
}
window
.$axios({
//这个接口本地调用要在vue.config.js 配置一下代理支持跨域 或者让后端做个方向代理的处理我们直接拿后端返回的接口
url: "https://restapi.amap.com/v3/geocode/regeo",
method: "get",
data: params,
params
})
.then(res => {
let data = res.data
if (data) {
let { addressComponent } = data.regeocode
let city = addressComponent.city.length != 0 ? addressComponent.city : addressComponent.province;//城市是省直辖县时返回为空 就直接显示省
let address = title ? title : addressComponent.streetNumber.street + addressComponent.streetNumber.number //街道+门牌号
let addString = addressComponent.province + city + addressComponent.district + addressComponent.township
this.selectInfo = {
addressAll: title ? addString + title : addString + address,
address: address,
province: addressComponent.province,
city: city,
district: addressComponent.district,
street: addressComponent.township,
}
this.showInfo = true
this.lngLat = `${point.lng},${point.lat}`
this.location = `${this.selectInfo.province},${this.selectInfo.city},${this.selectInfo.district},${this.selectInfo.street}`
if (!this.isToStreet) this.location = this.location + ',' + address
}
});
},
getAddress () {
this.show_ = false
top.window.$bus.$emit(`get-address-map-data${this.emitName ? '-' + this.emitName : ''}`, JSON.parse(JSON.stringify(this.selectInfo)))
}
},
mounted () {
let self = this;
document.addEventListener("keyup", function (e) {
if (e.keyCode == 13 ) {
self.handleSearch();
}
});
}
}
</script>
4.style部分
<style lang="scss" scoped>
::v-deep .map-wrap {
position: relative;
.search {
width: 410px;
margin: 16px 0 0 16px;
}
.search-result {
width: 350px;
margin-left: 16px;
padding: 10px 0;
margin-top: 5px;
background: #fff;
max-height: 300px;
overflow-y: auto;
.item {
padding: 4px 12px;
&:hover {
background: #f5f7fa;
}
i.el-icon-search {
margin-top: 3px;
font-size: 14px;
}
.mgr10 {
margin-right: 10px;
}
.title {
text-overflow: ellipsis;
overflow: hidden;
font-size: 14px;
padding-bottom: 4px;
}
.address {
line-height: 1;
font-size: 12px;
color: #b4b4b4;
margin-bottom: 5px;
}
}
}
.bm-view {
height: 400px;
.map {
width: 100%;
height: 100%;
}
}
.search-wrap {
position: absolute;
top: 0;
left: 0;
}
.input-with-select {
width: 410px;
.el-input__inner:focus {
border-color: #d1d5dc;
}
}
}
::v-deep .BMap_noprint {
&.anchorTL {
top: 16px !important;
right: 16px !important;
}
}
::v-deep .BMap_cpyCtrl {
display: none;
}
::v-deep .anchorBL {
display: none;
}
::v-deep .el-input-group__append,
.el-input-group__prepend {
background-color: #3788ee;
.el-icon-search {
color: #fff;
font-weight: 600;
font-size: 16px;
}
}
#container {
width: 750px;
height: 400px;
}
</style>