一、前言
最近工作中,客户要求使用地图展示省-市-县区三级业务关系,并且可实现地图三级钻取。过程中遇到了以下几个问题,在此经验分享,希望大家少走弯路。
1.业务地图与实际行政区域关系不完全一致。
2.不同权限的人进入到系统后,由于权限不同,所呈现的对应的地图,这个地图可以是省级地图、市级地图、县区级地图。
3.后期四级区域变更,需要灵活配置,而不是进行地图的二次开发调测。
针对以上问题,我们逐步解决。
二、地图灵活加载
假设 mapJson 为某区域地图的 geojson。我们只需要使用如下方式就可以进行地图加载
echarts.registerMap('my_area',mapJson);varchart=echarts.init(document.getElementById('area'));chart.setOption({……series:[{type:'map',map:'my_area',//要和echarts.registerMap()中第一个参数一致……}]……});从上面代码可以看到,我们只需要让echarts注册地图的名称和series中map的值保持一致就可以。下面是我的实际代码中进行的函数封装,mapname为地图文件的名称,也是地图对应区域的编码(adcode)。
functionmapRefresh(mapname,mapData){varjsurl=ctx+'ajax/libs/report/echarts/qinghaimap/'+mapname+'.json';$.get(jsurl,function(mapJson){echarts.registerMap(mapname,mapJson);optionGS.series[0].map=mapname;optionGS.geo.map=mapname;optionGS.series[0].data=mapData;myChartGS.setOption(optionGS);});};三、地图json文件的获取
3.1 地图基本区域获取
最新行政区划获取,基于高德地图API获取数据,下面是我的代码,基于python获取
importjsonimportrequestsdefparse_district(districtObj:dict,idx=1,parent_id=0):res=[]if'name'indistrictObj.keys():ifdistrictObj['level']=='street':returnres lng,lat=districtCenter(districtObj['center'])level=districtLevel(districtObj['level'])citycode=districtObj['citycode']ifisinstance(districtObj['citycode'],str)else''# {"citycode":"0379","adcode":"410300","name":"洛阳市","center":"112.434468,34.663041","level":"city"}# idx, districtObj['adcode'], districtObj['name'], level, citycode, lng, lat, parent_iditem={'id':idx,'adcode':districtObj['adcode'],'name':districtObj['name'],'level':level,'citycode':citycode,'lng':lng,'lat':lat,'parent_id':parent_id}res.append(item)parent_id=idx idx=idx+1ifisinstance(districtObj.get('districts'),list)andlen(districtObj['districts'])>0:forsubitemindistrictObj['districts']:subs=parse_district(subitem,idx,parent_id)res+=subs idx+=len(subs)returnresdefdistrictLevel(levelStr):map_val={'country':0,'province':1,'city':2,'district':3}returnmap_val[levelStr]defdistrictCenter(center):items=center.split(',')returnfloat(items[0]),float(items[1])# 结果保存为json数组defsaveJson(data):withopen('area_dict.json','w',encoding='utf-8')asfp:json.dump(data,fp,ensure_ascii=False,indent=4)print('Save json file: area_dict.json')# 保存为SQL脚本defsaveSqlFile(data,includeCreate=True):# +--------------+-------------+------+-----+---------+----------------+# | Field | Type | Null | Key | Default | Extra |# +--------------+-------------+------+-----+---------+----------------+# | area_id | int(11) | NO | PRI | NULL | auto_increment |# | area_code | char(6) | NO | MUL | NULL | |# | area_name | varchar(20) | NO | MUL | NULL | |# | level | tinyint(1) | NO | MUL | 0 | |# | city_code | char(4) | YES | | NULL | |# | longitudinal | int(11) | YES | | 0 | |# | lateral | int(11) | YES | | 0 | |# | parent_id | int(11) | NO | MUL | -1 | |# +--------------+-------------+------+-----+---------+----------------+createCode=""" CREATE TABLE `area_dict` ( `area_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '地区Id', `area_code` char(6) NOT NULL COMMENT '地区编码', `area_name` varchar(20) NOT NULL COMMENT '地区名', `level` tinyint(1) NOT NULL DEFAULT '0' COMMENT '地区级别(1:省份province,2:市city,3:区县district,4:街道street)', `city_code` char(4) DEFAULT NULL COMMENT '城市编码', `lng` int(11) DEFAULT '0' COMMENT '城市中心经度', `lat` int(11) DEFAULT '0' COMMENT '城市中心纬度', `parent_id` int(11) NOT NULL DEFAULT '-1' COMMENT '地区父节点', PRIMARY KEY (`area_id`), KEY `areaCode` (`area_code`), KEY `parentId` (`parent_id`), KEY `level` (`level`), KEY `areaName` (`area_name`) ) ENGINE=InnoDB AUTO_INCREMENT=3261 DEFAULT CHARSET=utf8 COMMENT='地区码表'; """withopen('area_dict.sql','w',encoding='utf-8')asfp:ifincludeCreate:fp.write(createCode)foritemindata:item['lng']=int(item['lng']*1e6)item['lat']=int(item['lat']*1e6)sql="INSERT INTO area_dict(`area_id`,`area_code`,`area_name`,`level`,`city_code`,`lng`,`lat`,`parent_id`) "+\"VALUES({id},'{adcode}','{name}',{level},'{citycode}',{lng},{lat},{parent_id});\n".format(**item)fp.write(sql)print('Save sql file: area_dict.sql')if__name__=="__main__":url='https://restapi.amap.com/v3/config/district?keywords=中国&subdistrict=3&key=[你的高德地图key]'response=requests.get(url)ifresponse.okandresponse.status_code==200:data=response.json()data=parse_district(data)print('Download data successful, total:{0}!'.format(len(data)))saveJson(data)saveSqlFile(data)else:print('Request error!')程序执行结束,会生成area_dict.sql和area_dict.json,方便我们入库进行后台管理。
3.2 地图geojson下载
我们使用上面生成的area_dict.json进行地图geojson下载
importrequestsimportjsonimportosdefloadDistrict(filename):data=[]withopen(filename,'r',encoding='utf-8')asfp:data=json.load(fp)returndatadefsaveGeoJson(areaCode,force=False):saveName='geoV3/{0}.json'.format(areaCode)ifnotforceandos.path.isfile(areaCode):returnNonebaseUrl='https://geo.datav.aliyun.com/areas_v3/bound/{0}_full.json'baseUrl2='https://geo.datav.aliyun.com/areas_v3/bound/{0}.json'ifareaCode[-2:]=='00':url=baseUrl.format(areaCode)else:url=baseUrl2.format(areaCode)print(url)response=requests.get(url)ifresponse.okandresponse.status_code==200:res_json=response.json()withopen(saveName,'w',encoding='utf-8')asfp:json.dump(res_json,fp,ensure_ascii=False)else:returnareaCodeif__name__=="__main__":districts=loadDistrict('area_dict.json')errorCodes=[]fordistrictindistricts:code=saveGeoJson(district['adcode'])ifnotcodeisNone:errorCodes.append(code)print(errorCodes)fordistrictindistricts:code=saveGeoJson(district['adcode'],district['name'],district['level'])ifnotcodeisNone:errorCodes.append(code)print(errorCodes)这个时候我们就已经把标准行政区的geojson全部下载到本地了,基于编码,还有文件,结合第二章,我们就已经可以实现中国区域地图的中国、省、市、县区的钻取。
其他下载可参考《实战 抓取安徽省所有市、县、镇矢量坐标数据》
四、地图区域定制
4.1 geojson解读
首先我们看过地图的geojson文件,其大概如下:
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"adcode":630105,"name":"城北区","center":[101.761297,36.648448],"centroid":[101.699377,36.680565],"childrenNum":0,"level":"district","acroutes":[100000,630000,630100],"parent":{"adcode":630100}},"geometry":{"type":"MultiPolygon","coordinates":[[[[101.74077987670899,36.6482446264917],[101.73983573913573,36.646617714744369],……]]]}}]}地图里面核心的几个参数
features[0].properties.adcode : 区域编码
features[0].properties.name : 区域名称
features[0].geometry.coordinates : 区域边沿的经纬度信息
4.1 地图加载
我们打开https://geojson.io,或者https://www.strerr.com/geojson/geojson.html 点击open->file
选择我们需要编辑的地图,这里我们打开了青海地图。
在右边的table区域就会展示当前地图所包含的子模块,然后我们按照下面操作,勾选出我们需要制定的区域。
最后我们在table区域进行区域编辑,就可以制作好我们的地图文件,最后点击save->geojson可以保存我们地图json压缩文件,也可以拷贝右边的json进行保存。