效果展示


需求:
1、实现高德地图输入地址自动提示功能 ,根据筛选结果,默认显示第一个结果
2、实现单击获取某个地点的经纬度和地址信息
3、实现筛选地址标注点
4、实现地图回显,再次打开地图定位到之前选中的地址展示详情
5、封装地图组件可在项目中任意地方使用
注意点:首先项目中需要引用高德地图,并且我同步引用了高德的PlaceSearch、AdvancedInfoWindow、Autocomplete这几个插件,高德提供同步引用和异步引用,异步引用的话,需要你自己去高德的文档看看
文档地址:https://lbs.amap.com/api/amap-ui/intro/
<script src="https://webapi.amap.com/maps?v=1.4.15&key=换成你自己的key&plugin=AMap.PlaceSearch,AMap.AdvancedInfoWindow,AMap.Autocomplete"></script>
首先发一份可直接打开看的vue文件
<template>
<basic-container>
<el-button @click="openMap">打开地图选择</el-button>
<el-dialog
title="地图选择"
:visible.sync="mapDialog"
width="80%"
:close-on-click-modal="false"
:before-close="cancelMap"
top="10vh"
>
<div class="over-hide">
<div id="myPageTop">
<table>
<tr>
<td>
</td>
</tr>
<tr>
<td>
<el-input
placeholder="请输入关键字进行查询"
v-model="inputAddress"
id="tipinput"
@clear="inputHandle"
@input="clickCancle"
clearable
></el-input>
</td>
</tr>
</table>
</div>
<div id="container" class="map"></div>
<br />
<br />
</div>
<span slot="footer" class="dialog-footer">
<div class="t-a-l">
<el-row class="infoAddressIpt">
<el-col :span="2">
<span>详细地址</span>
</el-col>
<el-col :span="22">
<el-input v-model="saveAddress"></el-input>
</el-col>
</el-row>
<span class="spb"
>重要提醒:地址标准格式**市**区**路**号。应按以上格式确认地址是否正确,如不正确,请自行修改,后期可能用于准考证上!</span
>
</div>
<el-button @click="cancelMap">取 消</el-button>
<el-button type="primary" @click="sureMap">确 定</el-button>
</span>
</el-dialog>
</basic-container>
</template>
<script>
export default {
data() {
return {
inputAddress: "",
map: "",
mapDialog: false,
saveLatLng: {},
saveAddress: "",
saveId: "",
saveLng: "",
saveLat: "",
};
},
methods: {
_initMap(value) {
var map;
var zoomVal = 0;
var centerVal = [];
if (this.saveLng != "" && this.saveLat != "") {
map = new AMap.Map("container", {
zoom: 16,
resizeEnable: true, //是否可缩放
isHotspot: true, //设置热点
visible: false,
center: [this.saveLng, this.saveLat], //初始地图中心点
});
} else {
map = new AMap.Map("container", {
resizeEnable: true, //是否可缩放
isHotspot: true, //设置热点
visible: false,
zoom: 11,
});
}
console.log(zoomVal, centerVal);
// var map = new AMap.Map("container", {
// zoom: 10,
// resizeEnable: true, //是否可缩放
// isHotspot: true, //设置热点
// visible: false,
// });
this.map = map;
//创建一个信息窗体
var infoWindow = new AMap.AdvancedInfoWindow({});
var placeSearch = new AMap.PlaceSearch({
city: "全国", //城市范围
map: map,
extensions: "all", //返回基本地址信息
});
// 添加工具栏
map.plugin(["AMap.ToolBar", "AMap.Scale"], () => {
// 工具条
const toolbar = new AMap.ToolBar();
// 比例尺
const scale = new AMap.Scale();
map.addControl(toolbar);
map.addControl(scale);
});
//地图点击事件
var _that = this;
map.on("hotspotclick", function (result) {
placeSearch.getDetails(result.id, function (status, result) {
if (status === "complete" && result.info === "OK") {
// console.log(result, "------------>>");
_that.$nextTick(() => {
_that.inputAddress = result.poiList.pois[0].name;
});
placeSearch_CallBack(result);
}
});
});
//回调函数(组装数据,设置窗体内容和位置)
function placeSearch_CallBack(data) {
console.log(data);
var poiArr = data.poiList.pois;
var location = poiArr[0].location;
// //添加marker
// var marker = new AMap.Marker({
// map: map,
// position: poiArr[0].location,
// });
// map.setCenter(marker.getPosition());
getAddress(
poiArr[0].location.lng,
poiArr[0].location.lat,
poiArr[0],
location
// marker
);
}
//组装弹窗信息
function createContent(poi, result) {
console.log(poi, "-------弹框信息", result);
let pName = "";
if (poi.pname == poi.cityname) {
pName = poi.cityname + poi.adname + poi.address;
} else {
pName = poi.pname + poi.cityname + poi.adname + poi.address;
}
pName = pName.replace("NaN", "");
//把所选择的地址赋值给输入框
_that.$nextTick(() => {
_that.inputAddress = poi.name;
_that.saveAddress = pName;
_that.saveId = poi.id;
});
console.log(pName);
//信息窗体内容
var s = [];
s.push(
'<div class="info-title">' +
poi.name +
'</div><div class="info-content">' +
"地址:" +
pName
);
s.push("经度:" + poi.location.lng);
s.push("纬度:" + poi.location.lat);
s.push("<div>");
s.join("<br>");
infoWindow = new AMap.InfoWindow({
content: s.join("<br/>"), //使用默认信息窗体框样式,显示信息内容
});
infoWindow.open(map, map.getCenter());
}
//获取具体的地址
// value1 经度2
// value2 纬度
// value3 具体地址信息对象
// value4 接口返回的location对象
function getAddress(value1, vulue2, value3, value4, value5) {
console.log(value1, vulue2, value3, value4, value5, "---------value");
infoWindow.setContent(createContent(value3, {}));
infoWindow.open(
map,
value4
// value5.getPosition()
); //开启信息窗体
}
//输入提示
var autoOptions = {
input: "tipinput",
datatype: "all",
citylimit: true,
};
var auto = new AMap.Autocomplete(autoOptions);
AMap.event.addListener(auto, "select", select); //注册监听,当选中某条记录时会触发
// AMap.event.addListener(auto, "complete", onComplete); // 返回定位信息
//为地图注册click事件获取鼠标点击出的经纬度坐标
map.on("click", function (e) {
// console.log(e, "------点击事件");
_that.saveLatLng = e.lnglat;
});
//监听搜索出来的标记点的点击事件
AMap.event.addListener(placeSearch, "markerClick", function (e) {
console.log(e, "------------点击搜索标记", e.data.location);
_that.saveLatLng = e.data.location;
// console.log(_that.inputAddress, e.data.name);
infoWindow.setContent(createContent(e.data, {}));
infoWindow.open(map, e.data.location); //开启信息窗体
});
//通过关键字搜索触发的select事件
function select(e) {
placeSearch.setCity(e.poi.adcode);
placeSearch.setCityLimit(true);
placeSearch.search(e.poi.name); //关键字查询查询
console.log(e, "------------》》》");
// this.saveLatLng = e.poi;
getAddress(
e.poi.location.lng,
e.poi.location.lat,
e.poi,
e.poi.location
);
}
if (value != "") {
//详情查询
placeSearch.getDetails(value, function (status, result) {
// console.log(status, result);
if (status === "complete" && result.info === "OK") {
placeSearch_CallBack(result);
}
});
}
},
autoSearch() {},
inputHandle() {
//清除所有覆盖物
this.map.clearMap();
this.saveAddress = "";
},
clickCancle(value) {
if (value == "" || value == undefined) {
//清除所有覆盖物
this.map.clearMap();
}
},
openMap() {
this.mapDialog = true;
this.$nextTick(() => {
this._initMap(this.saveId);
});
},
cancelMap() {
this.mapDialog = false;
this.saveId = "";
this.saveAddress = "";
this.saveLatLng = {};
this.inputAddress = "";
this.saveLat = "";
this.saveLn = "";
//清除所有覆盖物
this.map.clearMap();
},
sureMap() {
console.log(this.saveLatLng, this.saveAddress);
if (
JSON.stringify(this.saveLatLng) != "{}" &&
JSON.stringify(this.saveAddress) != ""
) {
this.mapDialog = false;
console.log(this.saveLatLng);
this.saveLat = this.saveLatLng.lat;
this.saveLng = this.saveLatLng.lng;
} else {
this.$message.warning("请选择一个地址");
}
},
},
beforeDestroy() {
this.map.destroy(); //销毁地图
},
};
</script>
<style lang="scss">
.map {
height: 100%;
width: 100%;
float: left;
}
.info-title {
font-weight: bolder;
color: #fff;
font-size: 14px;
line-height: 26px;
padding: 0 0 0 6px;
background: #25a5f7;
}
.info-content {
padding: 4px;
color: #666666;
line-height: 23px;
font: 12px Helvetica, "Hiragino Sans GB", "Microsoft Yahei", "微软雅黑", Arial;
}
.info-content img {
float: left;
margin: 3px;
}
.amap-info-combo .keyword-input {
height: auto;
}
.amap-info-content {
padding: 10px 26px 10px 10px;
}
.amap-info-close {
top: 15px;
}
#myPageTop {
/* position: fixed; */
/* right: 10%; */
top: 20px;
background-color: white;
width: 100%;
}
#myPageTop table,
#myPageTop tbody,
#myPageTop tbody input {
width: 100%;
}
#container {
margin-top: 10px;
margin-bottom: 10px;
height: 500px;
overflow: hidden;
overflow-y: hidden;
/* position: fixed; */
}
.amap-sug-result {
z-index: 9999 !important;
}
.el-card__body {
padding: 0;
}
</style>
<style lang="scss" scoped>
.over-hide {
overflow: hidden;
}
.t-a-l {
text-align: left;
margin-bottom: 15px;
}
.infoAddressIpt {
height: 40px;
line-height: 40px;
}
.spb {
color: #f56c6c;
font-size: 16px;
}
</style>
根据项目需求自己封装的组件(这份代码仅供参考哦),因为我的项目需求中,一个页面会有几处地方用到地图,所以每个地方的地图都需要唯一的id标识来区分哦;如果一个页面只需要用一次地图,是不用考虑这些问题的
封装的组件
<template>
<basic-container>
<el-button @click="openMap">打开地图选择</el-button>
<el-dialog
title="地图选择"
:visible.sync="mapDialog"
width="80%"
:close-on-click-modal="false"
:before-close="cancelMapClose"
top="10vh"
append-to-body
modal-append-to-body
v-if="creatDom"
>
<div class="over-hide">
<div id="myPageTop">
<table>
<!-- <tr>
<td>
<label>请输入关键字:</label>
</td>
</tr> -->
<tr>
<td>
<!-- <input id="tipinput" /> -->
<el-input
placeholder="请输入关键字进行查询"
v-model="inputAddress"
id="tipinput"
ref="inputBtn"
@clear="inputHandle"
@input="clickCancle"
clearable
></el-input>
</td>
</tr>
</table>
</div>
<div id="container" class="map" ref="mapRef"></div>
</div>
<span slot="footer" class="dialog-footer">
<div class="t-a-l">
<el-row class="infoAddressIpt">
<el-col :span="2">
<span>详细地址</span>
</el-col>
<el-col :span="22">
<el-input
v-model="saveAddress"
@input="inputInfoAddress"
></el-input>
</el-col>
</el-row>
<span class="spb"
>重要提醒:地址标准格式**市**区**路**号。应按以上格式确认地址是否正确,如不正确,请自行修改,后期可能用于准考证上!</span
>
</div>
<!-- <el-button @click="cancelMap">取 消</el-button> -->
<el-button @click="cancelMapClose">取 消</el-button>
<el-button type="primary" @click="sureMap">确 定</el-button>
</span>
</el-dialog>
</basic-container>
</template>
<script>
export default {
props: {
dataItem: String,
},
data() {
return {
inputAddress: "",
map: "",
mapDialog: false,
saveLatLng: {},
saveAddress: "",
saveId: "",
saveLng: "",
saveLat: "",
saveDetailInfo: {},
sbAddress: "",
flagSel: "",
startAddress: "",
endAddress: "",
creatDom: false,
};
},
methods: {
_initMap(value) {
var map;
var zoomVal = 0;
var centerVal = [];
if (
this.saveLng != "" &&
this.saveLat != "" &&
this.saveLng != null &&
this.saveLng != undefined &&
this.saveLat != null &&
this.saveLat != undefined
) {
map = new AMap.Map(this.$refs.mapRef, {
zoom: 16,
resizeEnable: true, //是否可缩放
isHotspot: true, //设置热点
visible: false,
center: [this.saveLng, this.saveLat], //初始地图中心点
});
} else {
map = new AMap.Map(this.$refs.mapRef, {
resizeEnable: true, //是否可缩放
isHotspot: true, //设置热点
visible: false,
zoom: 11,
});
}
console.log(zoomVal, centerVal);
// var map = new AMap.Map("container", {
// resizeEnable: true, //是否可缩放
// isHotspot: true, //设置热点
// visible: false,
// });
this.map = map;
console.log(map);
//创建一个信息窗体
var infoWindow = new AMap.AdvancedInfoWindow({});
var placeSearch = new AMap.PlaceSearch({
city: "全国", //城市范围
map: map,
extensions: "all", //返回基本地址信息
});
// 添加工具栏
map.plugin(["AMap.ToolBar", "AMap.Scale"], () => {
// 工具条
const toolbar = new AMap.ToolBar();
// 比例尺
const scale = new AMap.Scale();
map.addControl(toolbar);
map.addControl(scale);
});
//地图点击事件
var _that = this;
map.on("hotspotclick", function (result) {
placeSearch.getDetails(result.id, function (status, result) {
if (status === "complete" && result.info === "OK") {
console.log(result, "------------>>");
_that.sbAddress = "";
_that.$nextTick(() => {
_that.inputAddress = result.poiList.pois[0].name;
});
placeSearch_CallBack(result);
}
});
});
//回调函数(组装数据,设置窗体内容和位置)
function placeSearch_CallBack(data) {
var poiArr = data.poiList.pois;
var location = poiArr[0].location;
// //添加marker
// var marker = new AMap.Marker({
// map: map,
// position: poiArr[0].location,
// });
// map.setCenter(marker.getPosition());
getAddress(
poiArr[0].location.lng,
poiArr[0].location.lat,
poiArr[0],
location
// marker
);
}
//组装弹窗信息
function createContent(poi, result) {
console.log(poi, "-------弹框信息", result, "----", _that.flagSel);
let pName = "";
if (_that.flagSel == 1) {
pName = poi.district + poi.address;
} else {
if (poi.pname == poi.cityname) {
pName = poi.cityname + poi.adname + poi.address;
} else {
pName = poi.pname + poi.cityname + poi.adname + poi.address;
}
}
pName = pName.replace("NaN", "");
//把所选择的地址赋值给输入框
_that.$nextTick(() => {
_that.inputAddress = poi.name;
if (_that.sbAddress != "" && _that.sbAddress != null) {
_that.saveAddress = _that.sbAddress;
} else {
_that.saveAddress = pName;
}
console.log(_that.saveAddress, "-------", _that.flagSel);
_that.endAddress = _that.saveAddress;
_that.saveId = poi.id;
_that.saveDetailInfo = poi;
_that.saveLatLng = poi.location;
});
//信息窗体内容
var s = [];
s.push(
'<div class="info-title">' +
poi.name +
'</div><div class="info-content">' +
"地址:" +
pName
);
s.push("经度:" + poi.location.lng);
s.push("纬度:" + poi.location.lat);
s.push("<div>");
s.join("<br>");
infoWindow = new AMap.InfoWindow({
content: s.join("<br/>"), //使用默认信息窗体框样式,显示信息内容
});
infoWindow.open(map, map.getCenter());
_that.flagSel = "";
}
//获取具体的地址
// value1 经度2
// value2 纬度
// value3 具体地址信息对象
// value4 接口返回的location对象
function getAddress(value1, vulue2, value3, value4, value5) {
// console.log(value1, vulue2, value3, value4, value5, "---------value");
infoWindow.setContent(createContent(value3, {}));
infoWindow.open(
map,
value4
// value5.getPosition()
); //开启信息窗体
}
// input: _that.$refs.inputBtn,
// input: "tipinput",
//输入提示
var autoOptions = {
input: _that.$refs.inputBtn.$attrs.id,
datatype: "all",
citylimit: true,
};
console.log(autoOptions, "-------", this.$refs.inputBtn);
var auto = new AMap.Autocomplete(autoOptions);
AMap.event.addListener(auto, "select", select); //注册监听,当选中某条记录时会触发
// AMap.event.addListener(auto, "complete", onComplete); // 返回定位信息
//为地图注册click事件获取鼠标点击出的经纬度坐标
map.on("click", function (e) {
console.log(e, "------点击事件");
// _that.saveLatLng = e.lnglat;
_that.sbAddress = "";
});
//监听搜索出来的标记点的点击事件
AMap.event.addListener(placeSearch, "markerClick", function (e) {
console.log(e, "------------点击搜索标记", e.data.location);
_that.saveLatLng = e.data.location;
_that.sbAddress = "";
console.log(_that.sbAddress, e.data.name, "------");
infoWindow.setContent(createContent(e.data, {}));
infoWindow.open(map, e.data.location); //开启信息窗体
});
//通过关键字搜索触发的select事件
function select(e) {
placeSearch.setCity(e.poi.adcode);
placeSearch.setCityLimit(true);
placeSearch.search(e.poi.name); //关键字查询查询
console.log(e, "------------》》》");
// this.saveLatLng = e.poi;
_that.flagSel = 1;
_that.sbAddress = "";
getAddress(
e.poi.location.lng,
e.poi.location.lat,
e.poi,
e.poi.location
);
}
if (value != "") {
//详情查询
placeSearch.getDetails(value, function (status, result) {
// console.log(status, result);
if (status === "complete" && result.info === "OK") {
placeSearch_CallBack(result);
}
});
}
},
inputHandle() {
//清除所有覆盖物
this.map.clearMap();
this.saveAddress = "";
},
clickCancle(value) {
if (value == "" || value == undefined) {
//清除所有覆盖物
this.map.clearMap();
}
},
/**
* @description:
* @param {参数类型}value1 地图再次渲染的标识
* @param {参数类型}value 2 经度
* @param {参数类型}value 3 纬度
* @param {参数类型}value 4 地址
* @return
*/
getMapId(value1, value2, value3, value4) {
console.log(value1, value2, value3, value4);
this.creatDom = true;
this.saveId = value1;
this.saveLng = value2;
this.saveLat = value3;
this.sbAddress = value4;
this.startAddress = value4;
sessionStorage.setItem("addressVal", value4);
},
openMap() {
this.creatDom = true;
console.log(this.dataItem, this.saveId);
this.mapDialog = true;
this.$nextTick(() => {
this._initMap(this.saveId);
});
},
cancelMap() {
this.mapDialog = false;
this.saveId = "";
this.saveAddress = "";
this.saveLatLng = {};
this.inputAddress = "";
this.saveDetailInfo = {};
this.saveLat = "";
this.saveLng = "";
//清除所有覆盖物
this.map.clearMap();
//this.dataItem 父组件传个子组件的数据或者标识
// this.saveLat 纬度
// this.saveLng 经度
//this.saveAddress 详细地址
//this.saveLatLng 经纬度对象
//this.saveDetailInfo 详细地址对象
this.$emit(
"functionCancel",
this.dataItem,
this.saveLat,
this.saveLng,
this.saveAddress,
this.saveLatLng,
this.saveDetailInfo
);
this.map.destroy(); //销毁地图
this.creatDom = false;
},
cancelMapClose() {
this.mapDialog = false;
this.map.destroy(); //销毁地图
this.creatDom = false;
},
inputInfoAddress(value) {
this.endAddress = value;
},
sureMap() {
console.log(
this.saveLatLng,
this.saveAddress,
this.dataItem,
this.saveId,
this.saveDetailInfo
);
if (JSON.stringify(this.saveLatLng) != "{}") {
let getAddresss = sessionStorage.getItem("addressVal");
console.log(getAddresss);
this.startAddress = getAddresss;
if (this.saveAddress != "") {
if (this.startAddress != "" && this.startAddress != this.endAddress) {
const h = this.$createElement;
this.$msgbox({
title: "重要提示",
message: h("p", null, [
h("span", null, "您由初始地址 "),
h("span", { style: "color: red" }, this.startAddress),
h("span", null, " 变更为 "),
h("span", { style: "color: red" }, this.endAddress),
h("span", null, " 地址"),
h("span", null, "请确认!"),
]),
showClose: false,
showCancelButton: true,
confirmButtonText: "确定",
cancelButtonText: "取消",
})
.then((res) => {
this.saveLat = this.saveLatLng.lat;
this.saveLng = this.saveLatLng.lng;
this.mapDialog = false;
this.saveId = this.saveDetailInfo.id;
//this.dataItem 父组件传个子组件的数据或者标识
//this.saveId 地图再次渲染的凭证
// this.saveLat 纬度
// this.saveLng 经度
//this.saveAddress 详细地址
//this.saveLatLng 经纬度对象
//this.saveDetailInfo 详细地址对象
this.$emit(
"functionSure",
this.dataItem,
this.saveId,
this.saveLat,
this.saveLng,
this.saveAddress,
this.saveLatLng,
this.saveDetailInfo
);
this.startAddress = "";
this.endAddress = "";
sessionStorage.removeItem("addressVal");
this.map.destroy(); //销毁地图
this.creatDom = false;
})
.catch((err) => {
console.log(err, "---");
});
} else {
const h = this.$createElement;
this.$msgbox({
title: "重要提示",
message: h("p", null, [
h("span", null, " 最终的地址为 "),
h("span", { style: "color: red" }, this.endAddress),
h("span", null, " 请确认!"),
]),
showCancelButton: true,
showClose: false,
confirmButtonText: "确定",
cancelButtonText: "取消",
})
.then((res) => {
console.log(res);
this.saveLat = this.saveLatLng.lat;
this.saveLng = this.saveLatLng.lng;
this.mapDialog = false;
this.saveId = this.saveDetailInfo.id;
//this.dataItem 父组件传个子组件的数据或者标识
//this.saveId 地图再次渲染的凭证
// this.saveLat 纬度
// this.saveLng 经度
//this.saveAddress 详细地址
//this.saveLatLng 经纬度对象
//this.saveDetailInfo 详细地址对象
this.$emit(
"functionSure",
this.dataItem,
this.saveId,
this.saveLat,
this.saveLng,
this.saveAddress,
this.saveLatLng,
this.saveDetailInfo
);
this.startAddress = "";
this.endAddress = "";
sessionStorage.removeItem("addressVal");
this.map.destroy(); //销毁地图
this.creatDom = false;
})
.catch((err) => {
console.log(err, "---");
});
}
} else {
this.$message.warning("详细地址不能为空,请正确输入!");
}
} else {
this.$message.warning("未获取到经纬度信息,请选择一个地址!");
}
},
},
beforeDestroy() {
if (this.map != "") {
this.map.destroy(); //销毁地图
}
},
};
</script>
<style lang="scss">
.map {
height: 100%;
width: 100%;
float: left;
}
.info-title {
font-weight: bolder;
color: #fff;
font-size: 14px;
line-height: 26px;
padding: 0 0 0 6px;
background: #25a5f7;
}
.info-content {
padding: 4px;
color: #666666;
line-height: 23px;
font: 12px Helvetica, "Hiragino Sans GB", "Microsoft Yahei", "微软雅黑", Arial;
}
.info-content img {
float: left;
margin: 3px;
}
.amap-info-combo .keyword-input {
height: auto;
}
.amap-info-content {
padding: 10px 26px 10px 10px;
}
.amap-info-close {
top: 15px;
}
#myPageTop {
/* position: fixed; */
/* right: 10%; */
top: 20px;
background-color: white;
width: 100%;
}
#myPageTop table,
#myPageTop tbody,
#myPageTop tbody input {
width: 100%;
}
#container {
margin-top: 10px;
margin-bottom: 10px;
height: 400px;
overflow: hidden;
overflow-y: hidden;
/* position: fixed; */
position: relative;
background: rgb(252, 249, 242);
}
.amap-sug-result {
z-index: 9999 !important;
}
// .el-card__body {
// padding: 20px;
// }
</style>
<style lang="scss" scoped>
.over-hide {
overflow: hidden;
}
.t-a-l {
text-align: left;
margin-bottom: 15px;
}
.infoAddressIpt {
height: 40px;
line-height: 40px;
}
.spb {
color: #f56c6c;
font-size: 16px;
}
.el-card__body {
padding: 20px;
}
</style>
在父组件中引用封装好的组件
第一步首先需要引用

第二步使用 ,注意我是通过$refs 传值给子组件的哦,不是直接用props的哦


点击地图的确定事件,具体逻辑结构依据自己项目需求,我放出来了7个参数,根据自己需求使用哦

这是地图的取消事件 放出来6个参数,根据自己需求使用哦

