基于Leaflet的高德AOI数据在天地图底图可视化纠偏实践
# 前言 之前有朋友咨询有一份从高德地图获取的数据。在高德地图上展示时,位置都是没有问题的。但是在底图切换到天地图时,发现空间范围面发生了偏移。想咨询怎么解决这个问题。关于地图中的坐标系,这里不讲述过多的理论知识,关于坐标系的内容,大家可以自行查找一些互联网的资料来进行学习。国内的地图提供商,比如高德、百度、腾讯等等,都会做一些偏移。关于偏移的效果如下所示:  选择天地图作为在线底图是一种常见的做法,也是推荐的做法。如前文所述,在进行一些在线数据的采集时,会将不同的矢量数据在底图中进行展示,因此发生的矢量数据和底图有偏移的情况。如上图中的红色是从高德中采集的原始数据,即偏移的数据,白色范围是对应的在天地图中的准确数据。当然,如果您的底图也是采用高德的底图的话,那么则无需处理这种情况。 本文即在此需求背景下产生,博客内容主要讲述如何从高德地图中查找我们需要的AOI边界数据,如何将采集回来的AOI数据在Leaflet地图中展示,其次讲述使用JavaScript在前端进行高德数据到WGS84坐标的转换,最后综合展示纠偏前和纠偏后的数据,让您对当前的场景有一个综合的了解和熟悉。如果您当前也遇到了这类问题,不妨来这里看看博文。 # 一、高德地图中的AOI数据 AOI数据是兴趣面数据,对应的是POI即兴趣点数据。在空间点的分布当中,通过POI可以找到对应的AOI数据,比如一个小区,可以构建成一个AOI。这里也不深入的讲解什么是AOI,这里以高德地图为例,重点讲解如何在高德地图中查询我们需要的AOI数据,同时可以将高德的AOI数据进行相应的抓取。 ## 1、数据查询 首先我们在浏览器中打开高德地图,将弹出如下界面:  以上是高德地图的首页,跟我们之前自己实现的Leaflet地图功能类似,可以做地图的缩放,非常清晰的,可以在地图的左上角可以看到可以支持关键词检索。比如在地址检索框中输入“梅溪湖步步高”,可以看到系统做了以下检索:  可以看到,它在查询检索界面不仅将目标地址进行了列出,同时还在地图中展示了一个空间边界的范围,就是一个商场的外围边界。而这个外围边界就是指的AOI数据。 我们可以在控制台来看一下它的主要请求过程是怎么发生的。 ## 2、服务接口简介 为了能准确的获取目标兴趣点的边界数据,还需要对相关的接口进行介绍。主要分为两个接口。一个是获取目标兴趣点的列表信息,第二个是通过详情id获取坐标信息详情的接口。先来看下检索的过程是怎么处理的,打开网页的调试模式,如下图所示:  可以在监控窗口可以看到,系统访问的后台服务地址如下: ``` https://www.amap.com/service/poiInfo?query_type=TQUERY&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=16.74&city=430100&geoobj=112.855343%7C28.196778%7C112.866758%7C28.200526&keywords=%E6%AD%A5%E6%AD%A5%E9%AB%98%E6%A2%85%E6%BA%AA%E6%96%B0%E5%A4%A9%E5%9C%B0 ``` 其携带的请求参数如下所示:  在响应中可以看到有以下的数据列表:  返回的是一个POI的数据列表,打开具体的一条记录,请记住里面的ID字段,这个字典就是后面的数据关联对象。 尤其是打开详情的时候的信息。 ``` { "rating": "4.0", "tel": "", "typecode": "060000", "areacode": "0731", "address": "东方红路657号", "cityname": "长沙市", "display_brand": "", "shape_region": "", "longitude": "112.862798", "review_total": "", "cinemazuo_flag": "0", "diner_flag": "0", "id": "B0KADSUQ7M", "name": "步步高梅溪新天地假日广场", "group_flag": "0", "distance": "0", "entrances": [], "recommend_flag": "3", "exits": [], "adcode": "430104", "domain_list": [ { "type": "html", "id": "1015", "name": "poiclosed" }, { "type": "img", "id": "1003", "name": "icon" }, { "type": "html", "id": "1011", "name": "traffic" }, { "type": "text", "id": "1014", "name": "roadaoi" }, { "type": "button", "id": "1012", "name": "ext_btn" }, { "type": "webimg", "id": "1009", "value": "http://store.is.autonavi.com/showpic/c399c8adab0448847bfa1b8d698fd252", "name": "pic_info" }, { "type": "img", "id": "1008", "name": "overbooked" }, { "type": "img", "id": "1007", "name": "moreservice" }, { "type": "html", "id": "1006", "name": "tag" }, { "type": "text", "id": "1005", "name": "parent_info" }, { "type": "array", "name": "parent_other_rel", "id": "1004" }, { "type": "text", "id": "1010", "name": "business_area" }, { "type": "html", "id": "1002", "name": "deepinfo" }, { "type": "html", "id": "1001", "name": "price" }, { "type": "text", "id": "1013", "name": "aoi" } ], "newtype": "060000", "disp_name": "步步高梅溪新天地假日广场", "cpdata": "", "latitude": "28.196510", "discount_flag": "0" } ``` 在最后打开详情页面,可以找到AOI详情数据。如下图所示:  访问连接如下: ``` https://www.amap.com/detail/get/detail?id=B0FFHRXORE ``` 在返回的值中就可以找到对应的AOI数据,查看data节点下的spec,再打开mining_shape字段,如下:  到这里,基本就可以获取到高德的AOI数据。下面我们结合天地图来讲解如何进行web展示以及纠偏展示。 # 二、在天地图中展示AOI数据 将面的坐标点导到本地后,就可以将坐标位置展示出来。本节结合天地图和Leaflet来看一下如何将这些面展示出来。 ## 1、对面数据的处理 首先我们来一个真实的AOI输入,数据样例如下所示: ``` "112.869683,28.191884;112.868807,28.191039;112.86821,28.190464;112.867508,28.189842;112.867465,28.189826;112.867417,28.189832;112.867366,28.189852;112.867218,28.189914;112.867173,28.189945;112.86708,28.190037;112.866052,28.191339;112.865927,28.191468;112.865743,28.191696;112.865561,28.19198;112.86546,28.192143;112.864943,28.193369;112.864461,28.194713;112.864407,28.194901;112.863687,28.198129;112.863535,28.198951;112.86354,28.198996;112.863564,28.199039;112.863605,28.199068;112.86367,28.199087;112.864193,28.199117;112.864551,28.199109;112.864858,28.199091;112.866598,28.199148;112.867201,28.199252;112.868416,28.199481;112.868517,28.199511;112.868986,28.199696;112.869025,28.199704;112.86906,28.199706;112.869095,28.199697;112.869139,28.199679;112.870409,28.198994;112.870438,28.198966;112.870451,28.198938;112.870463,28.198907;112.87052,28.198537;112.870597,28.198195;112.870866,28.197445;112.870891,28.197386;112.871148,28.196907;112.871583,28.196115;112.871695,28.195868;112.872088,28.195;112.872085,28.194965;112.872075,28.194937;112.872056,28.194919;112.872032,28.194904;112.870381,28.194416;112.870349,28.194398;112.870313,28.194379;112.87029,28.194356;112.870269,28.194334;112.870255,28.194275;112.87023,28.194178;112.870231,28.194067;112.870262,28.193956;112.870301,28.193888;112.870388,28.193776;112.87045,28.193705;112.870515,28.193636;112.870627,28.193523;112.87066,28.193483;112.870677,28.193449;112.870686,28.193396;112.870689,28.193341;112.870653,28.192904;112.870648,28.192846;112.870631,28.192802;112.870606,28.192773;112.870267,28.192485;112.870243,28.192456;112.870236,28.192425;112.870223,28.192318;112.870218,28.192292;112.870212,28.192266;112.870194,28.192244;112.869794,28.191969;112.869683,28.191884"; ``` 可以看到,这是一个由多个坐标点连续而成的面。两个坐标点之间用;号隔开。而坐标点的经纬度则用逗号隔开。因此我们在Javascript中只需要先按分号分隔字符串,再用逗号分隔就可以形成一个连续的面坐标。关键代码如下: ``` function convertStr2DataArrayNoTrans(strInfo){ var resultData = new Array(); var dataArray = strInfo.split(";"); for(var i = 0;i 137.8347) || ((lat 55.8271) || false) } ``` 接下来,我们将面坐标的构建进行一个简单的封装,跟之前的无转换不同,这里包含了坐标的转换。 ``` function convertStr2DataArrayTrans(strInfo){ var resultData = new Array(); var dataArray = strInfo.split(";"); for(var i = 0;i< dataArray.length;i++){ var _tempLatLon = dataArray[i].split(","); //parseFloat() 这里一定要用parseFloat函数,否则+运算后会变成非数字,导致偏移失败。 var pointJson = gcj02towgs84(parseFloat(_tempLatLon[0]),parseFloat(_tempLatLon[1])); resultData.push([pointJson[1],pointJson[0]]); } return resultData; } ``` 在这里,请注意由于我们的坐标点都是用字符串来表示,因此在传参时一定要转成浮点型来计算,否则将无法正确的计算对应的值。接下来我们将转换后的值叠加到地图当中去: ``` L.polygon([ convertStr2DataArrayTrans(diyishifanStr) ],blueStyle).addTo(map).bindPopup("湖南第一师范学院东方红校区转换数据"); ``` 然后在页面中查看一下具体的面数据,为了有所区别,我们将转换后的数据用白色来描述边界。效果如下:  通过上图可以看到,根据面数据的大小不一,均进行一定的偏移。同时经过我们的数据纠偏操作,成功的将数据进行了天地图的吻合和叠加。通过以上的代码和教程,大家就能掌握具体的纠偏方法。 # 四、总结 以上就是本文的主要内容,博客内容主要讲述如何从高德地图中查找我们需要的AOI边界数据,同时讲解如何将采集回来的AOI数据如何在Leaflet地图中展示,其次讲述如何使用JavaScript在前端进行高德数据到WGS84坐标的转换,最后综合展示纠偏前和纠偏后的数据,让您对当前的场景有一个综合的了解和熟悉。行文仓促,定有许多不足支持,如有不足还恳请各位专家朋友在评论区留言指正,不甚感激。