一. 效果:输入后显示相关的地址列表,选中后出现标示图标和居中定位
1.初始化谷歌地图 在index.html加上谷歌api请求库
<script src="https://maps.googleapis.com/maps/api/js?key=申请到的谷歌地图密钥&v=weekly&libraries=geometry,places,marker" defer></script>
注意:libraries=geometry,places,marker 是支持的功能插件,不加有些功能不支持
2.页面上加载
<a-modal v-model:visible="openPopupTemp" force-render title="详细地址" width="1000px" @ok="handleOk" @cancel="handleCancel"><a-space direction="vertical" size="large" class="w-full" style="position: relative; margin-bottom: 20px;"><a-space><a-input v-model:value="searchQuery" placeholder="请输入地点名称" style="width: 600px" @input="handleInput" /><a-button type="primary" @click="handleInput">搜索</a-button></a-space><div v-if="predictionsList.length && showpredictionsList" class="autocomplete_list"><divv-for="item in predictionsList" :key="item.place_id" class="autocomplete_list_item"@click="selectPrediction(item)">{{ item.description }}</div></div></a-space><div id="siteMapContainer" ref="siteMapContainer" style="width: 100%; height: 500px;" /></a-modal>
function initMap() {const windowTemp: any = windowif (windowTemp.google) {const temp: any = windowTemp.googlegoogleMap = new temp.maps.Map(siteMapContainer.value, {center: { lat: latitude.value, lng: longitude.value },zoom: 8,mapId: 'DEMO_MAP_ID', // 需要id才能使用masker})temp.maps.event.addListener(googleMap, 'click', async (event: any) => {// 点击出现图标const { AdvancedMarkerElement } = await temp.maps.importLibrary('marker')Marker && Marker.setMap(null)Marker = new AdvancedMarkerElement({position: event.latLng,map: googleMap,})// 获取详细的地址const Geocoder = new temp.maps.Geocoder(googleMap)Geocoder.geocode({'latLng': event.latLng,}, (results: any, status: any) => {if (results[0].formatted_address) {searchQuery.value = results[0].formatted_addresslatitude.value = event.latLng.lat()longitude.value = event.latLng.lng()showpredictionsList.value = false}})})}
}
注意:
- mapId: ‘DEMO_MAP_ID’, // 需要id才能使用AdvancedMarkerElement 图标功能
- ant-modal需添加 force-render 属性才能够获取到siteMapContainer的dom元素,不然会报错!
3.输入查询服务
// 查询地址
function handleInput() {const windowTemp: any = windowconst temp: any = windowTemp.googleconst autocompleteService = new temp.maps.places.AutocompleteService()showpredictionsList.value = trueautocompleteService.getPlacePredictions({ input: searchQuery.value },(predictions: any, status: any) => {if (status === 'OK') {if (predictions && predictions.length > 0)predictionsList.value = predictionselsepredictionsList.value = []}},)
}
4.列表点击设置地址并显示图标+居中定位
// 设置地址
function selectPrediction(prediction: any) {// // 创建 PlacesService 对象const windowTemp: any = windowconst temp: any = windowTemp.googleconst placesService = new temp.maps.places.PlacesService(googleMap)// 获取地点的 Place IDconst placeId: any = prediction.place_id// 发起 Places API 请求placesService.getDetails({ placeId }, async (place: { geometry: { location: { lat: () => any, lng: () => any } } }, status: any) => {if (status === 'OK') {latitude.value = place.geometry.location.lat()longitude.value = place.geometry.location.lng()const { AdvancedMarkerElement } = await temp.maps.importLibrary('marker')Marker && Marker.setMap(null)Marker = new AdvancedMarkerElement({position: place.geometry.location,map: googleMap,})searchQuery.value = prediction.descriptionshowpredictionsList.value = false// 定位googleMap.setCenter(place.geometry.location)}})
}
待改进点:
- 点击查询的地址,服务返回的不够详细,需要找找其他服务
- 谷歌地图需要外网才能使用
二.外网申请
使用这个获取软件
https://tagcloud.lanzoue.com/icE800yez8ah
使用这个获取外网账号
https://www.xfltd.net/dashboard
谷歌地图api文档
https://developers.google.cn/maps/documentation/geocoding?hl=zh-cn
三.获取国外的geoJson实现省市区级联选择
全球行政区划的数据库
https://docs.gmt-china.org/6.1/dataset/gadm/
四.处理国外的geoJson组合成为树结构,给级联组件使用
返回来的数据是 “NL_NAME_1”: 一层 “NL_NAME_2”: 二层 “NL_NAME_3”: 三层
解析二层方法
function getTwoTree() {const temp: any = []const features: any = gadm41_THA_2.features// console.log('🚀 ~ onMounted ~ features:', features)// 找出相同的省份features && features.forEach((item: any) => {temp.push(item.properties.NL_NAME_1)})const lastList: any = [...new Set(temp)]const myList: any = []for (let index = 0; index < lastList.length; index++) {const item = lastList[index]const children = features.filter((fItem: any) => item === fItem.properties.NL_NAME_1)const tempchildren: any = []children && children.forEach((cItem: any) => {tempchildren.push({value: cItem.properties.NL_NAME_2,label: cItem.properties.NL_NAME_2,})})myList.push({value: item,label: item,children: tempchildren,})}addrArrOptions.value = myList
}
解析三层方法
function getThreeTree() {const temp: any = []const features: any = gadm41_CHN_3.featuresconsole.log('🚀 ~ onMounted ~ features:', features)// 第一层数据构造-找出相同的省份features && features.forEach((item: any) => {temp.push(item.properties.NL_NAME_1)})const oneList: any = [...new Set(temp)]const tempOne: any = []oneList.forEach((item: any) => {tempOne.push({ children: [], value: item, label: item })})// 第二层数据构造for (let i = 0; i < tempOne.length; i++) {const childrenOne: any = features.filter((fItem: any) => tempOne[i].label === fItem.properties.NL_NAME_1)const temp: any = []childrenOne.forEach((cItem: any) => {if (!temp.find((tItem: any) => tItem.label === cItem.properties.NL_NAME_2)) {temp.push({label: cItem.properties.NL_NAME_2,value: cItem.properties.NL_NAME_2,})}})tempOne[i].children = temp}// 第三层数据构造for (let i = 0; i < tempOne.length; i++) {for (let j = 0; j < tempOne[i].children.length; j++) {const childrenTwo: any = features.filter((fItem: any) => tempOne[i].children[j].label === fItem.properties.NL_NAME_2)const temp: any = []childrenTwo.forEach((cItem: any) => {if (!temp.find((tItem: any) => tItem.label === cItem.properties.NL_NAME_3) && cItem.properties.NL_NAME_3 !== 'NA') {temp.push({label: cItem.properties.NL_NAME_3,value: cItem.properties.NL_NAME_3,})}})tempOne[i].children[j].children = temp}}addrArrOptions.value = tempOneconsole.log('🚀 ~ 第三层数据构造:', tempOne)
}