el-cascader异步级联选择器选择省市区,在百度地图上显示坐标
大家好,我是南宫,上上周我去开了个需求评审,里面有几个细节我特别担心,特意花了两天去查资料,查的昏天黑地的。上周我开始写在地图上选择坐标的组件,写完以后想分享一下其中的经验,所以写了这篇博客。
可能不会涉及太多细节,主要是思路的分享。
① 级联选择器选择到的是id,怎么把选择到的id给百度地图API查询经纬度坐标?
我的级联选择器用的是公司内部自己的接口封装的,是异步的级联选择器,选择到的结果是一个数组,值为对应的行政编码。比如["35","3501","350102"]。
我确认过,用行政编码是无法到百度地图查出经纬度坐标的,但是省市区的名称可以(通过百度地图的地址解析功能可以根据省市区名称获取经纬度,如果传入数字找不到)。
所以核心就是,在选择完,拿到code以后,去获取选择的节点数据,然后拼接完整的省市区名称,然后调用百度地图的api去查询经纬度。
分享一部分的代码。
// 在级联选择器被回填以后,或者发生了change事件后,就去获取勾选的节点,并且通过parent找到所有父节点的数据,就可以拼接节点的名称了
getArea() {const nodes = this.$refs.nativeSelect.$refs.nativePlace.getCheckedNodes()console.log('nodes, 级联选择器勾选的节点', nodes)let name = nodes[0].data.areaNamelet parent = nodes[0].parentwhile (parent) {name = parent.data.areaName + ',' + nameparent = parent.parent}console.log('name拼接', name)this.areaName = name},
获取到名称以后,把名称拼接起来,拼接起来以后作为一个地址去调用百度地图地址解析的API:
(前面那段修改了areaName的值,下面这段代码是针对areaName的watch)
主要是调用BMapGL.Geocoder实例的getPoint方法,第一个参数是地址字符串,第二个参数是回调函数,第三个参数表示城市,也就是在哪个城市找这个地址,我们这里地址就是省市区,所以不使用第三个参数。
// 获取到完整的行政区域名称后,获取经纬度,设为中心点,并且定位到这里
areaName(val) {if (val) {var geocoder = new BMapGL.Geocoder()geocoder.getPoint(val, (rs) => {console.log('结果', rs)if (rs) {this.$refs.map.setCenter([rs.lng, rs.lat])this.mapClick([rs.lng, rs.lat])console.log('获取行政区域坐标', rs.lng, rs.lat)} else {this.$message.warning('行政区域定位失败')}})}},
(地图组件的封装和地图组件定位到对应坐标的代码我就不放出来了,反正重点是要获取到选择的省市区的经纬度坐标)
② 特殊情况下查不到经纬度坐标,怎么办?
我的这个需求是可以选择省市区,但是没有要求必须选到区,也可以只选到市级或者省级。
我发现如果只选择到省,或者是选择了香港澳门台湾,会直接返回北京的经纬度坐标。应该是getPoint方法的内部逻辑,如果实在找不到就返回北京的坐标。
但是这样的话,虽然不会报错,但是给我造成了困扰。
我提供一个解决思路——先判断是否只选择省,是就拼接省会城市去定位,需要注意自治区的判断。
(因为省是一大块地区,只能用经纬度范围而不是经纬度坐标来定义。但是如果是省级的单位,往往都是设在省会城市的,所以定位到省会没什么不妥。注意自治区也是省级,但是名字又带“区”,不能仅仅用选择到的名字是否带有“省”来判断是否选择了省级)
如果是港澳台,就去定位到特定的坐标,我去百度搜到了一个差不多的经纬度,如果匹配到,直接让地图定位对应的坐标。
provinceToCapital数据是省份和省会的对照索引表,这个数据是AI提供给我的,当然,下面这个代码也是AI写的,我给整合起来用了。
// 根据行政区域名称获取经纬度,如果选择的是省,就定位到省会城市getLocationByAddress(address) {var myGeo = new BMapGL.Geocoder() // 预处理地址if ((!address.includes('市') && !address.includes('区')) || address.includes('自治区')) {// 假设所有省份后面都加上省会城市名var capital = provinceToCapital[address]if (capital) {address += capital}}console.log('获取经纬度的地址', address)// 特殊处理特殊的地名if (address.includes('香港')) {const point = {lng: 114.25,lat: 22.25,}console.log(point.lng + ', ' + point.lat)this.$refs.map.setCenter([point.lng, point.lat])this.mapClick([point.lng, point.lat])console.log('获取行政区域坐标', point.lng, point.lat)} else if (address.includes('澳门')) {const point = {lng: 113.55,lat: 22.19,}console.log(point.lng + ', ' + point.lat)this.$refs.map.setCenter([point.lng, point.lat])this.mapClick([point.lng, point.lat])console.log('获取行政区域坐标', point.lng, point.lat)} else if (address.includes('台湾')) {const point = {lng: 121.5,lat: 25.05,}console.log(point.lng + ', ' + point.lat)this.$refs.map.setCenter([point.lng, point.lat])this.mapClick([point.lng, point.lat])console.log('获取行政区域坐标', point.lng, point.lat)} else {myGeo.getPoint(address, (point) => {if (point) {console.log(point.lng + ', ' + point.lat)this.$refs.map.setCenter([point.lng, point.lat])this.mapClick([point.lng, point.lat])console.log('获取行政区域坐标', point.lng, point.lat)} else {console.log('无法解析地址') // 可以选择返回一个预设的经纬度或者提示用户this.$message.warning('行政区域定位失败')}})}},