开发 AMapUI 组件库 参考手册 行政地理 行政区划浏览

行政区划浏览 最后更新时间: 2023年08月08日

DistrictExplorer(行政区划浏览) 提供了全国范围内到区县一级的行政区划数据(含边界),同时提供一些辅助功能,比如区划面绘制、事件监听,以及快速判断经纬度所属的子级区划等。

区划数据的组织方式如下图:一个AreaNode代表一份数据,包含父级(ParentFeature)区划和其下辖的多个子级(SubFeature)区划的信息,以父级区划的编码命名。区划信息的内容包括:区划编码(adcode),名称,中心位置(通常为政府所在地),边界信息等。

全国到区县是一个4级的树形结构,而DistrictExplorer却采用了如上所示的两级打包方式进行组织,原因在于边界数据的处理,具体来说:

  1. 边界需要抽稀至浏览器能够(快速)处理的程度:地理边界具备一定的分形特征,理论上可以无限长(想象一下用十倍,百倍,万倍的显微镜观察陆地边缘),但传输给浏览器的数据大小肯定是有限的(比如100k左右比较合适),绘制的点的数量也是有限的(比如1000个),这就意味着需要有选择性的保留一小部分节点,这就是边界的抽稀。
  2. 第二,区划的周长不同,抽稀强度也应有所不同:比如,全国的边界周长远远大于北京市朝阳区的边界周长。如果每百米取一个点(仅示意),对北京朝阳区可能刚刚好,但全国的边界数据就会非常大,或者说,此时全国的边界过于精细了;相反,如果采用每万米取一个点,朝阳区的边界可能会缩略到一个点,这样又太简略了。
  3. 第三,边界抽稀存在“传导”问题:边界是有共享性的,比如北京市延庆区和河北省共享一部分边界,河北省和内蒙古共享一部分边界,内蒙古又和全国共享一部分边界。这么“传导”下来,区到全国的抽稀强度应该是相同的(和第二点存在冲突),否则就会出现共享的边界不能重合的情况(对同样的边界抽取了不同的节点)。

DistrictExplorer做了目的性的取舍,重点针对两级浏览(比如全国范围内显示省级区划,某省范围内显示市级区划等)的场景,优先保证在一千像素高度时,父级“像素可辩”,子级“严丝合缝”。具体做法就是:上下级一起打包成一个AreaNode,独立进行边界抽稀。从最终的数据大小来看,单个AreaNode所用的数据文件大小在15k~150k之间,平均60k左右(gzip后在30k),加总的大小大致相当于区域查询服务提供的边界数据的 1/10

两级打包也存在一个明显的弊端,即同一个区划会出现在两个AreaNode(一个作为子级,一个作为父级)中,而且边界数据因抽稀强度不同而不同。比如下图,同样是香港特别行政区(区划编码 810000),在代表全国的AreaNode(下图左侧,编码100000)中作为子级区划(SubFeature),在代表香港的AreaNode(下图右侧,编码810000)中作为父级区划(ParentFeature)。左侧以全国为尺度进行抽稀,放大到10级后,相对右侧以香港自身为尺度,明显丢失了边界的曲折细节以及若干外围小岛,显得"直来直去"、“粗枝大叶”。

建议开发者在产品设计时把上述“弊端”作为一个约束考虑进去,随着地图的放大,引导用户切换到低级区划的AreaNode单独查看,这一点类似于文件夹,不是一次性全部浏览,而是一层层展开。AreaNode自身也提供了一个最佳缩放级别(IdealZoom)的信息,供开发者在设计切换场景时参考。

浏览器支持:

现代浏览器和 IE9 及以上 

名词释义

名称

说明

区划编码(adcode) 

区域编码由6位数字组成,唯一标识一个区划。比如:

全国:100000

北京:110000,河北:130000(省级区划通常后四位为0)

杭州:330100 (市级区划通常后两位为0)

杭州滨江区: 330108 (区县级)

全国的区划信息见 这里

区域节点(AreaNode)

一个AreaNode由父级区划和所辖的子级区划构成,并以父级区划的编码命名。

AreaNode对应的编码列表见这里注意:区县级以及部分没有子级的区划(比如台湾,东莞等)不在该列表中,也没有对应的AreaNode,它们的数据存在于其父级对应的AreaNode中。比如东莞的数据可以通过加载广东省的AreaNode,然后调用 getSubFeatureByAdcode 获取。

最佳缩放级别(IdealZoom)

AreaNode实例的一个属性(通过getIdealZoom方法获取),地图处于在该级别时,AreaNode对应的整体区域的显示高度通常超过1000像素,同时边界数据保留了个位像素级的细节。在该级别以上,随着地图的放大,边界将越发显得“直来直去”(如上图左侧的香港)。

特征(Feature)

Feature直接取自GeoJSON。GeoJSON是一种标准的地理数据结构,相关的支持较多。AreaNode之中无论父级区划(ParentFeature)还是子级区划(SubFeature),都是类似如下所示的格式。

JavaScript

{
	"type": "Feature",
	"properties": {
		"adcode": 100000, //区划编码
		"name": "全国", //区划名称
		"center": [116.3683244, 39.915085], //区划中心点,通常为区划政府所在地
		"childrenNum": 34 //子级区划的数量,可能为0
	},
	"geometry": {
		"type": "MultiPolygon",
		"coordinates": [
			[
				[
					[180.0, 40.0],
					[180.0, 50.0],
					....
				]
			],
			[
				[
					[-170.0, 40.0],
					[-170.0, 50.0],
					....
				]
			]
		]
	}
}

请注意其中 MultiPolygon 的嵌套层级,首先是多个Polygon(比如海南省下辖多个小岛),每个Polygon会有多个Ring(环),每个Ring由多个经纬度坐标数组构成。大家通常理解的多边形可能更多是Ring这个概念,也就是不带内环的多变形。

直接利用coordinates数据时请留意其结构,可参见带环多边形的示例

如何使用

1、引入UI组件库

2、加载DistrictExplorer(模块名:ui/geo/DistrictExplorer

//加载DistrictExplorer,loadUI的路径参数为模块名中 'ui/' 之后的部分 
AMapUI.loadUI(['geo/DistrictExplorer'], function(DistrictExplorer) {
   //启动页面
   initPage(DistrictExplorer);
});

function initPage(DistrictExplorer) {
   //创建一个实例
   var districtExplorer = new DistrictExplorer({
      map: map //关联的地图实例
   });

   var adcode = 100000; //全国的区划编码

   districtExplorer.loadAreaNode(adcode, function(error, areaNode) {

      if (error) {
         console.error(error);
         return;
      }

      //绘制载入的区划节点
      renderAreaNode(districtExplorer, areaNode);
   });
}

function renderAreaNode(districtExplorer, areaNode) {

   //清除已有的绘制内容
   districtExplorer.clearFeaturePolygons();

   //just some colors
   var colors = ["#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00"];

   //绘制子级区划
   districtExplorer.renderSubFeatures(areaNode, function(feature, i) {

      var fillColor = colors[i % colors.length];
      var strokeColor = colors[colors.length - 1 - i % colors.length];

      return {
         cursor: 'default',
         bubble: true,
         strokeColor: strokeColor, //线颜色
         strokeOpacity: 1, //线透明度
         strokeWeight: 1, //线宽
         fillColor: fillColor, //填充色
         fillOpacity: 0.35, //填充透明度
      };
   });

   //绘制父级区划,仅用黑色描边
   districtExplorer.renderParentFeature(areaNode, {
      cursor: 'default',
      bubble: true,
      strokeColor: 'black', //线颜色
      fillColor: null,
      strokeWeight: 3, //线宽
   });

   //更新地图视野以适合区划面
   map.setFitView(districtExplorer.getAllFeaturePolygons());
}

示例中心

接口文档

构造参数

参数名称

类型

说明

map

AMap.Map

地图对象实例。仅仅获取数据,不涉及地图相关的操作时,可以不设置。 

eventSupport 

Boolean

 是否启用事件支持,默认false。开启后,可以在map上识别鼠标位置所属的区划,有两点请开发者注意:

  1. 事件监听的对象是map,因此,地图上的覆盖物(多边形,Marker等)需要设置bubble:true, 即允许事件冒泡到地图上

  1. 需要执行setAreaNodesForLocating方法设置用于位置识别的AreaNodes,详见下。

preload

Array.<adcode>

需要预加载的adcode列表

方法

事件

注意:需要开启 eventSupport 以及 setAreaNodesForLocating 。

事件示例

事件名称

参数

说明

featureClick

event:{type:String, originalEvent:event} 

               originalEvent为原始事件,通常由map触发,手动触发时可能为空

feature:Feature 相关的feature

鼠标点击feature对应的区域时触发

featureMouseover

同 featureClick 

鼠标移入feature对应的区域触发 

featureMouseout

同 featureClick  

鼠标移出 feature对应的区域触发  

featureMousemove

同 featureClick  

鼠标在feature对应的区域上移动时触发 

outsideClick

同 featureClick,但feature为空

鼠标点击了无法识别的区域时触发

区域节点 - AreaNode

AreaNode实例不能直接创建,需要由上述的 loadAreaNode 或者 loadMultiAreaNodes 方法获取。 

方法名称

返回值

说明

getAdcode()

Number

返回父级区划的adcode

getBounds()

AMap.Bounds 

返回当前区域节点的整体经纬度范围

getIdealZoom()

Number

返回查看该区域的最佳级别,仅推荐性质。

getName()

String

返回父级区划的name

getProps()

Object

返回父级区划的属性(parentFeature.properties)

getLocatedSubFeature

(position:AMap.LngLat)

Feature

返回某个经纬度位置所属的子级区划,区域外返回null。该方法性能较高(每秒可达百万次),但不够精确(相对于逆地理编码服务),原因在于它是纯粹的几何判断,从而受限于feature中边界数据的精确程度。

getLocatedSubFeatureIndex (position:AMap.LngLat) 

Number

返回某个经纬度位置所属的子级区划的索引(针对 SubFeatures 数组中),区域外返回 -1 。

getParentFeature()

Feature

返回父级区划对应Feature

getSubFeatures()  

Array.<Feature>

返回该区域中全部的子级区划Feature数组

getSubFeatureByAdcode(

adcode:number) 

Feature

返回子级区划中adcode匹配的子级Feature

getSubFeatureByIndex(

index:number) 

Feature

返回子级区划中对应索引位置的子级Feature

groupByPosition(

points:Array.<Point>, 

getPosition:function)

Array.<{

//所属子级区划索引

subFeatureIndex: number,

//所属子级区划

subFeature: Feature

//分组点的索引

pointsIndexes: Array.<number>,

//分组点

points: Array.<*>

}>

根据所属的子级区划,将传入的位置点进行分组。Point可以是任意格式,只要能配合 getPosition 返回经纬度即可,参数类型为:

@param  {*} Point 数组元素

@param  {number} pointIndex 数组元素对应的索引 

@return {AMap.LngLat|Array.<number>} 

返回经纬度实例(AMap.LngLat)或者经纬度数字组成的数组([lng, lat])

区划分组示例

返回顶部 示例中心 常见问题 智能客服 公众号
二维码