vue 使用高德地图制作一个搜索,地图选址的组件
效果展示
引入高德地图
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=你的key去高德申请很快&plugin=AMap.MouseTool,Amap.PlaceSearch,Amap.Geocoder"></script>
子组件,上完整代码
- dom中basic-dialog是我们自己封装的弹窗组件,可以改为自己的弹窗组件 如element的el-dialog
- 组件的回显通过show方法传入一个对象包含经纬度和地址名称
- 需要子组件emit给父组件的对象中包含什么字段可以自己组装通过submit方法传出去
<template>
<basic-dialog title="选择位置" :visible="visible" width="55%" @close="close" custom-class="sm-padding-dialog">
<div class="top-search">
<el-input v-model="searchInput" placeholder="请输入内容" class="search-input"/>
<el-button type="primary" @click="searchAddress">搜索</el-button>
</div>
<div ref="map" class="map"/>
<div id="panel"/>
<span slot="footer" class="dialog-footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</span>
</basic-dialog>
</template>
<script>
// var zoom = 16;
export default {
name: 'MapChoose',
data() {
return {
// dialog
visible: false,
modal: {},
id: '',
// map
map: null,
mouseTool: null,
polygon: null,
markers: null,
placeSearch: null,
searchInput: '',
temporaryObj: {} // 点击之后暂存数据
};
},
methods: {
// open事件
show(row) {
this.visible = true;
if (row) {
this.modal = row;
}
console.log(this.modal, 'this.modal');
this.initMap();
},
// 初始化地图
initMap() {
this.$nextTick(() => {
const that = this;
// 地图初始化
// 设置中心点
let center = '';
if (this.modal.location) center = this.modal.location.split(',');
this.map = new AMap.Map(this.$refs.map, {
resizeEnable: true,
center,
zoom: 16
});
// 建立地图搜索服务
AMap.service(['AMap.PlaceSearch'], () => {
// 构造地点查询类
this.placeSearch = new AMap.PlaceSearch({
pageSize: 5, // 单页显示结果条数
pageIndex: 1, // 页码
citylimit: false, // 是否强制限制在设置的城市内搜索
map: this.map, // 展现结果的地图实例
panel: 'panel', // 结果列表将在此容器中进行展示。
autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
renderStyle: 'default'
});
});
// 搜索出来的地址列表增加点击事件,点击之后赋值
const onComplete = (row) => {
console.log(row);
const { data } = row;
this.temporaryObj.location = data.location.lng + ',' + data.location.lat;
this.temporaryObj.address = data.address + '-' + data.name;
if (this.markers) this.map.remove(this.markers);
};
AMap.event.addListener(this.placeSearch, 'listElementClick', onComplete);
// 添加工具栏
this.map.plugin(['AMap.ToolBar', 'AMap.Scale'], () => {
// 工具条
const toolbar = new AMap.ToolBar();
// 比例尺
const scale = new AMap.Scale();
this.map.addControl(toolbar);
this.map.addControl(scale);
});
// 回显已有marker
if (this.modal && this.modal.location) {
const location = this.modal.location.split(',');
this.markers = new AMap.Marker({
position: new AMap.LngLat(location[0], location[1]),
title: this.modal.name
});
this.markers.setMap(this.map);
}
// 地图点击标点
this.map.on('click', e => {
const lng = e.lnglat.lng;
const lat = e.lnglat.lat;
// 点击之后获得经纬度,根据经纬度通过反编译获得详细地址
AMap.plugin('AMap.Geocoder', () => {
const geocoder = new AMap.Geocoder({
// city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
city: ''
});
const lngLat = [e.lnglat.lng, e.lnglat.lat];
geocoder.getAddress(lngLat, (status, result) => {
if (status === 'complete' && result.info === 'OK') {
// result为对应的地理位置详细信息
that.temporaryObj.location = lng + ',' + lat;
if (that.markers) that.map.remove(that.markers);
that.markers = new AMap.Marker({
position: new AMap.LngLat(lng, lat)
});
that.markers.setMap(that.map);
that.temporaryObj.address = result.regeocode.formattedAddress;
that.temporaryObj.name = '';
openInfo(result.regeocode.formattedAddress, lngLat);
}
});
});
});
/**
* 打开marker信息窗体
* @param add 地址
* @param lngLat 经纬度数组
*/
const openInfo = (add, lngLat) => {
// 构建信息窗体中显示的内容
const info = [];
info.push("<div class='input-card content-window-card'>" + add + '</div>');
const infoWindow = new AMap.InfoWindow({
content: info.join(''), // 使用默认信息窗体框样式,显示信息内容
offset: new AMap.Pixel(0, -45)
});
infoWindow.open(that.map, lngLat);
};
});
},
// 搜索服务
searchAddress() {
this.placeSearch.search(this.searchInput);
},
// submit事件
submit() {
console.log(this.modal, 'ssss');
Object.assign(this.modal, this.temporaryObj);
this.$emit('mapOk', this.modal);
this.close();
},
// close事件
close() {
// 销毁地图
this.temporaryObj = {};
if (this.map) this.map.destroy();
if (this.markers) this.markers = null;
this.visible = false;
}
}
};
</script>
<style lang="scss" scoped>
#panel {
position: absolute;
background-color: white;
max-height: 90%;
overflow-y: auto;
top: 120px;
right: 50px;
width: 320px;
}
.top-search{
display: flex;
flex-wrap: nowrap;
justify-content: flex-start;
position: absolute;
top: 80px;
right: 50px;
z-index: 1;
width: 320px;
.search-input{
margin-right: 10px;
}
}
.map {
width: 100%;
height: 70vh;
}
.button-group {
position: absolute;
right: 12px;
bottom: 65px;
z-index: 1;
.tips {
color: red;
font-size: 12px;
line-height: 18px;
}
}
#myPageTop {
padding: 8px;
position: absolute;
top: 60px;
right: 50px;
background: #fff;
border: 1px solid #cccccc;
}
</style>
父组件使用,组件为全局注册,表单中的样式自己写
// 打开的方法使用ref调用子组件中的方法打开弹窗
this.$refs.mapChoose.show(this.clickRow); // 打开地图
此处的this.clickRow是将下面的对象传给子组件,子组件将选择的点回显到地图上,如果是第一次打开的话 就将里面的值置空就行
{
address: "四川省成都市青羊区西御河街道东华正街人民中路一段5号院"
contentUEditor: ""
location: "104.068455,30.660047"
name: ""
parentCode: "0"
parentName: "无上级"
reseauLeaderUserinfoCode: ""
reseauType: ""
reseauUserinfoCodesValue: Array(0)
shortName: ""
}
// 使用
<mapSelectLocation ref="mapChoose" @mapOk="mapOk"/>
// 地址赋值
mapOk(val) {
if (val) {
this.modelForm.address = val.address;
this.modelForm.location = val.location;
} else {
this.modelForm.address = '';
this.modelForm.location = '';
}
}
打印出来val的值看看
address: "四川省成都市青羊区西御河街道东华正街人民中路一段5号院"
contentUEditor: ""
location: "104.068455,30.660047"
name: ""
parentCode: "0"
parentName: "无上级"
reseauLeaderUserinfoCode: ""
reseauType: ""
reseauUserinfoCodesValue: Array(0)
shortName: ""