效果展示
需求:
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%; 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; 100%; } #myPageTop table, #myPageTop tbody, #myPageTop tbody input { 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%; 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; 100%; } #myPageTop table, #myPageTop tbody, #myPageTop tbody input { 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个参数,根据自己需求使用哦