效果展示
需求:
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個參數,根據自己需求使用哦