使用背景
在很多实际项目中都需要用到地图,不管是腾讯地图还是高德地图或是其他的地图,其实都是大差不差的。别人已经帮我们封装完毕,直接调用 api 即可。这次公司需要在添加或编辑的时候,能在地图中显示设备的位置,并可以搜索地址后获取经纬度。具体如图所示。
实现步骤
由于我们使用的是 vue3,所以我们应该将这个地图做成一个组件,以便于复用。之前公司已经有一个最基础的地图组件,所以我们需要在最基础的显示组件上加上这些业务逻辑
编写页面结构
1 2 3
| <div> <div :id="mapId" class="mapDiv"></div> </div>
|
这是原本最基础的页面样式,我们需要加上搜索框,以及经纬度搜索框。其实实现还是比较容易的,因为这些控件实际上是浮在地图之上的,所以我们让地图的父元素定位开启,接着我们写入基本结构,大概是这样。
1 2 3 4 5
| <div> <div :id="mapId" class="mapDiv"></div> <div class="search-wapper"></div> </div>
|
我们给这个容器加上 position:absolute,接着就是正常写结构即可。因为我们这个控件可能是有些地方需要,有些地方不需要。所以我们在组件上写 props。
由于搜索地址的输入框与经纬度的输入不会同时出现,所以我再设一个变量用于切换两个输入框。
逻辑实现
我们通过上面编写 html 和一些基本的 vue 代码已经实现了页面的显示。现在我们需要实现模糊搜索的功能。
实际上我们是使用到了高德 api 中的 autoComplete.search 方法,该方法会根据模糊输入的查询到相对的地址。
1 2 3 4 5 6 7 8 9 10 11 12
| this.debouncedChangeAddress = _.debounce((value) => { this.searchAddressLoading = true; autoComplete.search(value, (status, result) => { if (status === "complete" && !_.isEmpty(result.tips)) { this.options = result.tips; } else { this.options = []; ElMessage.warning("暂无搜索地址"); } this.searchAddressLoading = false; }); }, 1000);
|
这里使用 lodash 的 debounce 做防抖操作,然后我们将这个方法绑定到 elementUi 中的下拉框中的:remote-method=”debouncedChangeAddress”。这样我们就实现了查询功能,但是查询只是返回了 address 并不是经纬度,所以我们需要使用高德的地址查询 api 也就是 getLocation。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| getCoordinates(address) { this.map_loading = true; this.geocode.getLocation(address, (status, result) => { if (status === 'complete' && result.geocodes.length) { let lnglat = result.geocodes[0].location; const { lat, lng } = lnglat; this.latitude = lat; this.longitude = lng; this.addSearchMarker(lng, lat); } else { console.log('根据地址查询位置失败'); } this.$emit('mapClickInfo', { detailedAddress: address, siteLng: this.longitude, siteLat: this.latitude }); this.map_loading = false; }); },
|
这里我封装成一个方法,当我们点击 select 的相的时候调用这个方法,将传入的 address 转化为经纬度。
到这里其实已经完成了从输入模糊查询到变为经纬度,接下来我们还需要根据经纬度查询具体位置,其实就是调用 getAddress 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| getLocation(siteLng, siteLat) { this.map_loading = true; this.geocode.getAddress([siteLng, siteLat], (status, result) => { let detailedAddress = '';
if (status === 'complete' && result.regeocode) { detailedAddress = result.regeocode.formattedAddress; } else { ElMessage.error( i18n.global.t('page.dialog.actionFb.lngandlatQueryFailed') ); } this.$emit('mapClickInfo', { detailedAddress, siteLng, siteLat }); this.map_loading = false; }); },
|
这样就能通过经纬度反过来查询到地址。到此我们基本完成了这个功能
总结
其实这个逻辑并不困难,但是需要懂得如何查api文档。