效果图:
我们将学习如何创建一个前端地图应用程序,该应用程序集成了高德地图API,允许用户进行地点搜索、选择和标记,以及执行逆地理编码以获取地址信息。我们将使用Vue.js框架来构建应用程序,并结合高德地图的功能来实现这些功能。
步骤1:准备工作
在开始之前,确保你已经注册并获得了高德地图API的密钥。你可以在高德地图开放平台注册并获取密钥。这个密钥将用于访问地图服务。
高德开放平台:注册账号(https://lbs.amap.com/)) 申请小程序应用的 key
应用管理(https://console.amap.com/dev/key/app)) -> 我的应用 -> 创建新应用
步骤2:引入高德地图JavaScript API 在index.html添加以下代码
在Vue组件的**
<script type="text/javascript"> window._AMapSecurityConfig = { // serviceHost:'您的代理服务器域名或地址/_AMapService', // // 例如 :serviceHost:'http://1.1.1.1:80/_AMapService', securityJsCode: "你的安全秘钥", } </script> <script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.15&key=你的key&plugin=AMap.MarkerClusterer,AMap.Autocomplete,AMap.Geocoder,AMap.DistrictSearch"></script> <style>
步骤3:创建Vue组件
在Vue.js应用程序中创建一个组件,用于处理地图功能。你可以使用以下模板作为起点:
<template> <div> <div class="search-container"> <a-input v-model="searchKeyword" placeholder="输入关键字" style="width: 500px;"></a-input> <a-button @click="getAutoCompleteResults">搜索并定位</a-button> </div> <ul class="ul"> <li class="li" v-for="(result, index) in autoCompleteResults" :key="index" @click="selectLocation(result)"> {{ result.name }} </li> </ul> <div id="map" style="width: 100%; height: 400px;"></div> </div> </template>
这个模板包括一个搜索输入框、一个搜索按钮、一个建议列表和一个地图容器。
步骤4:调用高德地图方法
/** * 逆地理编码 */ getReverseGeocoding(location){ AMap.plugin('AMap.Geocoder', () => { const geocoder = new AMap.Geocoder({}); var lnglat = [location.longitude,location.latitude] var lastlocation = {lng:location.longitude,lat:location.latitude} geocoder.getAddress(lnglat, (status, result) => { if (status === 'complete' && result.info === 'OK') { // result为对应的地理位置详细信息 var regeocode=result.regeocode this.mapobj = { location: lastlocation, city: regeocode.addressComponent.city, formattedAddress: regeocode.formattedAddress, }; this.emitMapobjToParent(); } }) }) }, /** * 输入提示 */ getAutoCompleteResults() { if (this.searchKeyword) { // 使用高德地图的Autocomplete服务获取模糊查询的建议结果 AMap.plugin("AMap.Autocomplete", () => { const autoComplete = new AMap.Autocomplete({}); autoComplete.search(this.searchKeyword, (status, result) => { if (status === "complete" && result.info === "OK") { this.autoCompleteResults = result.tips; } }); }); } else { this.autoCompleteResults = []; } },
1. 逆地理编码 (getReverseGeocoding 方法)
这个方法的主要目的是将给定的经度和纬度坐标转换为地理位置信息,例如城市和格式化地址。以下是该方法的步骤:
- 使用高德地图的 AMap.Geocoder 插件,首先创建了一个逆地理编码对象 geocoder。
- 将传递给方法的 location 参数解构为 longitude 和 latitude。
- 创建一个 lnglat 数组,其中包含经度和纬度信息。
- 创建一个 lastlocation 对象,保存 location 的经纬度信息。
- 调用 geocoder.getAddress(lnglat, callback) 方法来执行逆地理编码。callback 函数在逆地理编码完成后被调用。
- 在 callback 函数中,检查逆地理编码的状态 (status) 和信息 (result.info) 是否为 ‘complete’ 和 ‘OK’。只有在状态和信息都满足时才继续处理结果。
- 如果逆地理编码成功,将结果中的地理位置详细信息保存在 regeocode 变量中。
- 使用 regeocode 中的信息创建一个 mapobj 对象,包括位置 (location)、城市 (city) 和格式化地址 (formattedAddress)。
- 最后,调用 emitMapobjToParent() 方法将 mapobj 传递给父组件,以供进一步处理或显示。
2. 输入提示 (getAutoCompleteResults 方法)
这个方法用于执行输入提示,根据用户输入的搜索关键词获取建议的地点列表。以下是该方法的步骤:
- 首先,检查是否存在用户输入的搜索关键词 (this.searchKeyword)。
- 如果搜索关键词存在,它创建了一个新的 AMap.Autocomplete 实例,该实例用于执行模糊查询。
- 使用 autoComplete.search(this.searchKeyword, callback) 方法,发送搜索关键词并提供一个回调函数 callback。
- 在回调函数中,检查返回的状态 (status) 和信息 (result.info) 是否为 ‘complete’ 和 ‘OK’。只有在满足这两个条件时才继续处理结果。
- 如果输入提示成功,将结果中的建议地点列表保存在 this.autoCompleteResults 中,以供用户界面显示。
- 如果搜索关键词为空,它会清空 this.autoCompleteResults,以确保不显示旧的建议结果。
步骤5:完整代码
<template> <div> <div class="search-container"> <a-input v-model="searchKeyword" placeholder="输入关键字" style="width: 500px;"></a-input> <a-button @click="getAutoCompleteResults">搜索并定位</a-button> </div> <ul class="ul"> <li class="li" v-for="(result, index) in autoCompleteResults" :key="index" @click="selectLocation(result)"> {{ result.name }} </li> </ul> <div id="map" style="width: 100%; height: 400px;"></div> </div> </template> <script> import { getAction, httpAction, postAction } from '../../api/manage' export default { data() { return { map: null, selectMode: false, selectedLocation: null, marker: null, // 添加一个保存标记的变量 searchKeyword: "", autoCompleteResults: [], mapobj: {}, url: { queryAddress: '/jeecg-customers/car/carGaode/queryAddress', geoCode: '/jeecg-customers/car/carGaode/geoCode', }, }; }, mounted() { // 创建地图对象 this.map = new AMap.Map("map", { zoom: 10, // 设置地图缩放级别 center: [114.16129136801659, 22.64461948509109], // 初始化地图中心点 }); console.log('sdfasf') // 监听地图点击事件 this.map.on("click", this.handleMapClick); }, methods: { addMarker2(location) { console.log(location) // 先移除已有的标记 if (this.marker) { this.map.remove(this.marker); } // 在地图上添加标记 this.marker = new AMap.Marker({ position: new AMap.LngLat(location.longitude, location.latitude), map: this.map, }); var lastlocation = [ Number(location.longitude), // 经度 Number(location.latitude), // 纬度 ]; this.map.setCenter(lastlocation); this.map.setZoom(18); // 设置选中的标记 this.selectedLocation = { longitude: location.longitude, latitude: location.latitude }; // this.getReverseGeocoding(this.selectedLocation); }, /** * 选择点位 */ toggleSelectMode() { // 切换选择模式 this.selectMode = !this.selectMode; if (!this.selectMode) { // 退出选择模式时,移除标记并清空已选择的位置 this.map.remove(this.marker); this.selectedLocation = null; } }, /**地图点击事件 * @param {Object} e */ handleMapClick(e) { // 处理地图点击事件 // if (this.selectMode) { // 如果在选择模式下点击地图,则添加标记 const { lng, lat } = e.lnglat; this.addMarker({ longitude: lng, latitude: lat }); // console.log(e) // } }, /**添加标记 * @param {Object} location */ addMarker(location) { // 先移除已有的标记 if (this.marker) { this.map.remove(this.marker); } // 在地图上添加标记 this.marker = new AMap.Marker({ position: new AMap.LngLat(location.longitude, location.latitude), map: this.map, }); // 设置选中的标记 this.selectedLocation = { longitude: location.longitude, latitude: location.latitude }; this.getReverseGeocoding(this.selectedLocation); }, /** * 逆地理编码 */ getReverseGeocoding(location) { //传递参数 const locationString = location.longitude + "," + location.latitude const Params = { location: locationString, } //页面显示 var lastlocation = { lng: location.longitude, lat: location.latitude } getAction(this.url.geoCode, Params).then((res) => { this.mapobj = { location: lastlocation, city: res.result.locationName, formattedAddress: res.result.distance, }; this.emitMapobjToParent(); }); }, /** * 输入提示 */ getAutoCompleteResults() { if (this.searchKeyword) { //调用后台接口 const Params = { address: this.searchKeyword, } getAction(this.url.queryAddress, Params).then((res) => { console.log(res) if(res.result.length>0){ this.autoCompleteResults = res.result; // 遍历数组中的每个地点对象,并重新赋值location字段为包含lng和lat属性的对象 this.autoCompleteResults.forEach(autoCompleteResult => { const locationString = autoCompleteResult.location; const locationArray = locationString.split(","); const longitude = Number(locationArray[0]); // 经度 const latitude = Number(locationArray[1]); // 纬度 // 重新赋值location字段为包含lng和lat属性的对象 缺少偏移量 autoCompleteResult.location = { lng: longitude, lat: latitude, }; }); }else{ this.$message.info('高德地图未匹配到数据'); } }); } else { this.autoCompleteResults = []; } }, /**选择地址 * @param {Object} result */ selectLocation(result) { console.log(result) // 在地图上显示选定的位置 this.addMarker3(result.location); this.mapobj = { location: result.location, city: result.district, formattedAddress: result.name, }; this.emitMapobjToParent(); }, addMarker3(location) { console.log(location, '输入提示添加标点') // 先移除已有的标记 if (this.marker) { this.map.remove(this.marker); } // 在地图上添加标记 this.marker = new AMap.Marker({ position: new AMap.LngLat(location.lng, location.lat), map: this.map, }); var lastlocation = [ Number(location.lng), // 经度 Number(location.lat), // 纬度 ]; this.map.setCenter(lastlocation); this.map.setZoom(18); // 设置选中的标记 this.selectedLocation = { longitude: location.lng, latitude: location.lat }; }, /** * 给父组件传值 */ emitMapobjToParent() { this.$emit('mapobj-changed', this.mapobj); }, }, }; </script> <style> /* 样式可以根据需求进行调整 */ #map { margin-bottom: 10px; } .ul { list-style: none; padding: 0; margin: 0; max-height: 150px; overflow-y: auto; border: 1px solid #ccc; } /* 每个列表项的样式 */ .li { cursor: pointer; padding: 10px; /* 增加内边距,提高可点击区域 */ border-bottom: 1px solid #ccc; transition: background-color 0.2s; /* 添加渐变效果 */ } /* 鼠标悬停时更改背景颜色 */ .li:hover { background-color: #f0f0f0; } /* 最后一个列表项的底部边框不显示 */ .li:last-child { border-bottom: none; } .search-container { text-align: center; /* 水平居中 */ } </style>