省市区县GeoJSON地图数据:DataV与ECharts接入、坐标系与避坑指南

📅 发布时间:2026/10/13 18:35:20
省市区县GeoJSON地图数据:DataV与ECharts接入、坐标系与避坑指南
简介阿里专用DataV.GeoAtlas全国GeoJSON省市区县数据包专为需要中国行政边界地理信息的开发者、数据分析师与可视化项目团队打造。数据源自阿里云DataV平台由Python脚本爬取整理覆盖全国省、市、区县三级行政区域GeoJSON格式便于直接用于地图绘制、DataV大屏、GIS分析与前端可视化开发。压缩包共13012个文件包括13010个json地理数据文件与2个Python爬取脚本整体大小80.87MB目录按行政编码组织检索定位十分方便。数据更新至2020年8月不含乡镇、街道等子域适合需要省市区县粒度数据的常见场景。目前已有3171人学习下载。通过本包可获得全套标准GeoJSON边界数据及配套爬虫脚本省去逐个行政区手工拼接的麻烦直接调用即可快速搭建可视化地图提升项目开发效率。1. 阿里 DataV.GeoAtlas 全国省市区县 GeoJSON为什么这套边界数据值得先搞定做地图可视化的人大概率都经历过在网上反复搜省市区县边界数据的阶段找回来的要么精度差到没法看要么字段命名乱到要挨个改。DataV.GeoAtlas 是阿里 DataV 配套的行政区划 GeoJSON 数据源这份「全国省市区县 json 数据」被标成阿里专用核心原因是它的字段和层级直接沿用了 DataV 地图组件的规范——adcode、name、level、centroid 都齐全组件拿过去不用再映射。rar 里打包了含子域和不含子域两套形态不含子域只有省级轮廓含子域则带上所有下级区划边界。它能解决什么省去从零整理全国边界的脏活让你把时间花在业务数据和交互上。适合正在做数据大屏、地图下钻、区域分析的前端与后端同学也适合刚接触地图可视化的新人拿来当第一份练手数据。2. 含子域与不含子域怎么选理解这份 rar 的层级、结构与坐标拿到 rar 之后第一件事不是解压就开画。很多人栽在第一步没搞懂「子域」是什么意思文件选错结果地图渲染出来要么没有下钻能力要么数据量大到页面卡死。这一章把这份数据的三个底层问题讲清楚子域是什么、JSON 里面到底长什么样、坐标又是什么体系。这三个问题搞明白了后面接入任何框架都不会跑偏。2.1 含子域与不含子域两种模式到底差在哪「子域」在这里指的是直接下级行政区。DataV.GeoAtlas 在线的区划选择器里选中任意一级行政区后下载区域会给出「不含子域」和「含子域」两个选项。选浙江省不含子域只输出浙江省整体轮廓含子域输出浙江省轮廓外加省内 11 个地级市的轮廓。全国包同理不含子域是 34 个省级行政区的轮廓集合含子域则在省级轮廓之上把所有地级市的边界也一起打包。这两个模式没有谁更好只有谁更合适。大多数场景下只做省级聚合展示比如「各省销售额排名」用不含子域就够了文件小、加载快但如果你想做「点击省下钻到市、再下钻到区县」这类联动交互必须用含子域否则市级的边界数据还得另找。我的习惯是先确认交互设计里有没有下钻没有就一律用不含子域省得白背几十 MB 的体积。对比项不含子域含子域数据体积小大要素数量多一个数量级要素内容仅当前层级的轮廓当前层级 所有直接下级轮廓加载速度快明显变慢需考虑按需加载典型场景全国按省着色、省级对比分析省市联动下钻、两级边界同时展示使用建议只做省级维度的展示需要区域钻取或同时画两级边界如果你下载的是单省含子域要注意它带的是「省 市」两级下载单市含子域带的是「市 区县」两级。全国含子域则是「省级 地市级」两级不会再往下包含区县级。想拿到全国区县级的边界必须逐省或逐市下载再合并这也是很多人拿到 rar 之后还要自己写合并脚本的原因。2.2 GeoJSON 内部结构properties 里的 adcode、name 与坐标数组解压后随便打开一个 json 文件本质上是一个 GeoJSON 的 FeatureCollection。每个 Feature 代表一个行政区核心信息都在 properties 里。下面是一个典型的省级要素骨架实际文件里 coordinates 会被非常长的数字数组占满这里用省略号代替{ type: Feature, properties: { adcode: 330000, name: 浙江省, center: [120.15, 30.28], centroid: [120.11, 29.21], childrenNum: 11, level: province, parent: { adcode: 100000 } }, geometry: { type: MultiPolygon, coordinates: [ [ [ [120.12, 30.35], [120.18, 30.42] ] ] ] } }几个字段单独说明。adcode 是行政区划代码省级两位数、地市级四位、区县级六位这是后续做拆分和关联业务数据的唯一可靠标识。name 是中文名称适合展示但不能当唯一键用。center 是官方标注的城市中心点centroid 是几何质心两者在标注文字位置时差别很大我用 center 做标签定位用 centroid 做聚合计算。childrenNum 直接告诉你这个行政区下面有多少个子域与含子域文件里的 feature 数量可以互相校验。geometry 的 type 要么是 Polygon要么是 MultiPolygon。省级边界通常都是 MultiPolygon因为可能包含飞地、岛屿等多块不相连的面。coordinates 的嵌套层级是固定的Polygon 是三维数组MultiPolygon 是四维数组。写代码遍历坐标时不要写死层级先判断 type 再决定遍历深度否则遇到多面体直接越界报错。用 Python 处理时如果只取第一个 Polygon飞地和小岛会全部丢失下钻时图型明显缺一块。2.3 坐标系与精度这份数据是 GCJ-02叠加底图前必须知道的事这份数据最容易被忽略的坑是坐标系。DataV.GeoAtlas 输出的 GeoJSON 用的是 GCJ-02 坐标系也就是俗称的火星坐标。它跟 GPS 设备直接采集的 WGS-84 坐标之间存在几十米到几百米的偏差具体偏移量随经纬度变化没有固定公式。这个设计国内很多地图服务都在用原因不展开但你要知道这份数据叠到使用 WGS-84 的底图上边界会整体往一个方向偏看起来就像整块地图被平移了。判断方法很简单取某个省的 center 坐标丢进一个明确用 GCJ-02 的地图底图里搜一下如果落点落在省会城市中心说明数据是 GCJ-02如果落在城外几公里你就要开始排查坐标系。验证成本极低我建议解压后先做这个验证再大规模开发别等所有功能做完才发现底图和边界对不上。如果项目底图必须用 WGS-84常见做法是引入 coordtransform 这类库做坐标转换把 GeoJSON 里每个坐标点遍历转换后重新生成新文件。注意转换后的边界会有一点形变这是坐标系转换的正常代价。除了坐标系还要对精度有预期——这份数据面向可视化展示边界做过抽稀简化区县级轮廓在放大到街道级别时会显得粗糙。做宏观分析没问题做精确面积计算或工程测绘就不要依赖它误差会超出你的容忍范围。3. 从 rar 到能交互的地图ECharts 与 DataV 的两种接入路径数据本身不会产生价值跑进渲染引擎才是起点。主流落地路径有两条通用图表库路线和 DataV 大屏路线。前者自由度高想怎么定制都行后者省事字段规范对齐了就基本零配置。这一章把两条路线的最小可运行方案都写出来并附上把全国包拆成单省单市文件的脚本。建议你先把 ECharts 这条跑通理解数据怎么被消费再去用 DataV 组件排查问题时思路会清晰很多。3.1 最小接入ECharts 5 直接吃 GeoJSONECharts 的 map 系列通过 registerMap 注册 GeoJSON之后就能像使用内置地图一样使用它。最简代码如下import * as echarts from echarts; import geoJson from ./assets/geoData_全国_不含子域.json; echarts.registerMap(china, geoJson); const chart echarts.init(document.getElementById(map)); chart.setOption({ tooltip: { trigger: item, formatter: {b}: {c} }, series: [ { type: map, map: china, roam: true, label: { show: true, fontSize: 10 }, data: [ { name: 浙江省, value: 123 }, { name: 广东省, value: 456 } ] } ] });registerMap 是全局注册同一个 GeoJSON 只注册一次多个图表实例可以共用。series 里的 data 通过 name 字段与 GeoJSON 里的 properties.name 匹配值会覆盖到对应的区块上。roam 开启后允许缩放和平移做下钻交互时建议打开否则用户只能看固定视角。label.show 控制行政区名字是否直接显示在地图上省级通常开启区县级开启后文字会挤成一团建议用 tooltip 代替。一个容易忽略的点import 一个 json 文件需要构建工具支持Vite 默认支持Webpack 5 也内置了 JSON 模块旧版本则需要配 json-loader。如果你在浏览器里直接打开 HTML 文件没有构建工具就用 fetch 加载本地 json 文件但要注意本地文件协议下 fetch 会被浏览器拦截需要起一个本地静态服务。我一般用 Vite 起 dev server 调试省掉各种协议问题。3.2 按需求拆分用 Python 脚本把全国包重组成单省单市文件全国含子域包一次加载渲染地市级 feature 全塞进去体积和渲染压力都很大。常见做法是先用脚本拆好前端在下钻时按需请求单个文件。拆分脚本不复杂核心就是 adcode 的长度规则import json import os from collections import defaultdict src geoData_全国_含子域.json # 换成你从 rar 里解压出的实际文件名 out_dir split os.makedirs(out_dir, exist_okTrue) with open(src, encodingutf-8) as f: data json.load(f) features data.get(features, []) # 按 adcode 长度分组2 位省级、4 位市级、6 位区县级 groups defaultdict(list) for feat in features: props feat.get(properties, {}) adcode str(props.get(adcode, )) level props.get(level, ) if len(adcode) 2 or level province: groups[province].append(feat) elif len(adcode) 4 or level city: groups[city].append(feat) elif len(adcode) 6 or level district: groups[district].append(feat) # 每组导出为一个独立的 FeatureCollection for level_name, feats in groups.items(): out_path os.path.join(out_dir, f{level_name}.json) with open(out_path, w, encodingutf-8) as f: json.dump({type: FeatureCollection, features: feats}, f, ensure_asciiFalse) print(f{level_name}: {len(feats)} 个 feature - {out_path})脚本逻辑分三步读取全国包按 adcode 长度把全部 feature 分成省、市、区县三组再分别写出。adcode 不是严格按长度区分所有情况直辖市的市辖区 adcode 是 6 位但它属于区县级一些特殊省级单位的直接下级也是 4 位此时 level 字段是更可靠的判断依据。所以我用len(adcode) 2 or level province这种双条件兜底建议你拿到文件后先打印几条 properties 看看 level 字段取值再决定是否调整条件。如果要拆成「浙江省含子域」这种单省文件改成按 adcode 前缀过滤province_code 33 # 浙江省的省级前缀按需替换 province_feats [ feat for feat in features if str(feat.get(properties, {}).get(adcode, )).startswith(province_code) ] with open(zhejiang_full.json, w, encodingutf-8) as f: json.dump({type: FeatureCollection, features: province_feats}, f, ensure_asciiFalse)用 startswith 匹配前缀能把浙江省及省内所有地级市一次性筛出来。这里有个细节省级 adcode 是 2 位市级 adcode 前两位恰好就是所属省的前缀所以 startswith 天然满足「省含子域」的筛选需求。拆完记得打印 count 跟 properties.childrenNum 对一对数量不一致说明原包有缺失别急着删除原始 rar。3.3 DataV 组件这边的接法上传 GeoJSON 与自定义边界在 DataV 的大屏画布里地图组件默认就能识别这份数据。常见做法是新建一个地图组件数据源切换到 GeoJSON 类型把 rar 里解压出的 json 内容粘贴进去或者直接上传文件。组件会读取 properties 里的 name 和 adcode自动完成区域匹配不需要像 ECharts 那样手动调 registerMap。这也是「阿里专用」这个描述最直接的体现——字段规范完全对齐少掉一层适配代码。如果你做省市联动DataV 组件里通常需要配置「区域下钻」或「层级切换」行为告诉组件当前展示的是省级还是市级。这里的关键是组件能下钻到哪一级取决于你喂给它的数据有没有下一级的 feature。喂全国不含子域最多到省级喂全国含子域能到地市级想再往下到区县必须单独准备区县级 GeoJSON。我踩过的坑是以为组件自带全国区县级数据结果下钻到一半就空白了。记住组件只负责渲染你提供的 GeoJSON不会自动去拉更多层级。如果大屏场景只需要「省 → 市」两级全国含子域一份文件就能覆盖这是最省事的组合。4. 省市区县 GeoJSON 接入避坑5 个常见的翻车现场与排查方法这一章专门记踩坑。以下五类问题基本覆盖了用这份数据做地图可视化的绝大多数翻车现场每条按「现象 → 原因 → 解决」展开。你在开发过程中如果遇到地图显示异常、交互错乱、性能卡顿优先来这里对照排查。4.1 边界整体漂移对不上底图现象地图边界跟底图叠加时整片区域往东南方向偏移省市轮廓和底图上的道路、标注有明显错位。放大之后偏移量越发明显看起来像是两套不同来源的地图叠在一起。原因数据坐标系不一致。DataV.GeoAtlas 这份数据是 GCJ-02而某些底图用的是 WGS-84 或者基于 WGS-84 的球面墨卡托投影。两个坐标系之间存在非线性偏移不是简单平移能修正的。很多人拿着这份 GeoJSON 直接叠到 WGS-84 的底图服务上渲染出来必然是整体漂移。解决先确认底图服务用的坐标系。如果底图也是 GCJ-02直接使用没有任何问题。如果底图是 WGS-84写一个转换脚本遍历所有坐标点做 GCJ-02 到 WGS-84 的转换重新生成一份新 GeoJSON。注意转换后会出现轻微形变和边界抖动这是正常的转换脚本运行一次把结果存成新文件不要在每次前端渲染时实时转换性能扛不住。4.2 name 字段重复导致下钻区域错乱现象做「省 → 市 → 区县」三级下钻时点击某个市地图高亮的却是另一个市或者 tooltip 里显示的名称和点击位置对不上。排查数据后发现多个 feature 的 name 完全一样。原因行政区划中「市辖区」「县」「自治州」这类名称重复率极高。比如多个地级市下面都有叫「市辖区」的区级单位在 GeoJSON 里它们的 name 都是「市辖区」而 ECharts 的 data 默认按 name 匹配遇到重复 name 就不知道把值赋给谁了。同理省级数据里也可能出现两个同名的下级单位。解决放弃用 name 做匹配一律改用 adcode。前端业务数据里带上 adcode 字段ECharts 配置里用 nameMap 把 adcode 映射成地图要素的匹配键或者干脆在数据处理阶段把重复 name 改写成「市名 区名」保证唯一性。DataV 组件由于原生读 adcode基本不会遇到这个问题但如果你把数据拿给其他框架用务必先检查 name 是否有重复。4.3 全国含区县文件加载卡顿现象页面初始化时白屏时间很长地图渲染出来之后拖动和缩放掉帧严重浏览器控制台提示图层绘制耗时过长。用 Performance 面板看耗时集中在地图初始绘制阶段。原因含子域的全国包包含数百个 feature每个 feature 的 coordinates 又包含大量顶点整体数据量达到几十 MB 级别。前端一次性加载并渲染这么多 GeoJSON 顶点无论是 parse 还是 draw 都会产生明显性能开销低端设备上甚至直接把页面卡死。解决三条路并行。第一数据上做按需拆分把全国包拆成省级文件下钻到哪一级才加载哪一级的 json这是治本的办法。第二用 turf.simplify 对边界做简化抽稀在可接受精度范围内把顶点数量砍掉一半以上体积能大幅缩小。第三渲染层面开启 ECharts 的渐进渲染或图层分块策略至少保证首屏能先画出来。不要指望用户机器性能多好大屏项目跑在老旧工控机上的情况很常见。4.4 解压后打开中文乱码、属性丢失现象在 Windows 上解压 rar用记事本或 Excel 直接打开 json 文件中文全部变成乱码有些文件甚至打不开提示格式错误。用代码读取时部分文件解析失败。原因文件本身是 UTF-8 编码但 Windows 默认的记事本在读取无 BOM 的 UTF-8 文件时会按照本地化编码去解析导致中文乱码。Excel 直接打开 json 更不靠谱它不识别这种结构。属性丢失则可能是中间环节用了错误编码转换比如用某些老旧解压工具或文本编辑器保存时把编码改掉了。解决编码问题不需要改文件改工具。代码读取时强制指定 UTF-8 编码Python 里就是open(path, encodingutf-8)已经写在第 3 章的脚本里了。日常查看用 VSCode 打开右下角能确认实际编码不要用 Excel 打开 json。如果你需要把数据导入数据库或表格工具先写脚本转成 CSV再用数据库客户端导入全程指定 UTF-8。另外解压工具尽量用支持中文文件名的现代工具避免文件名本身出现乱码导致路径匹配不上。4.5 海面附注框要素把地图下钻搞乱现象渲染全国数据时地图右下角出现一个悬浮的面状图形位置在海洋区域点击它有时会触发区域选中导致下钻逻辑异常。查看 GeoJSON 后发现它也是一个 Featureproperties 里没有正常的行政区 adcode。原因全国包在文件层级上除了省市级行政区还包含海面附注框这类示意性要素。它是为了在地图边缘标注海域范围用的本身不是行政区没有 6 位标准 adcode但混在 features 数组里一起被渲染。ECharts 不区分这是不是行政区全部画出来下钻时自然会出现一个不属于任何省的「区域」。解决加载数据后处理阶段就把这类要素过滤掉。判断条件不能只看 name最稳妥的办法是检查 properties 里有没有符合规范的 adcode或者 adcode 是否为纯数字 6 位。代码实现就是在拆分脚本里加一行过滤if not adcode.isdigit() or len(adcode) ! 6: continue把不合法的要素直接剔除。注意不要用 level 字段做唯一判断有些附注要素的 level 可能缺失而行政区要素的 level 一定在已知的可枚举范围内。过滤之后再跑下钻逻辑就不会出现海洋区域被点击的情况了。5. 进阶用三个小习惯把省市区县边界数据维护成自己的基础库这份数据不是一次性的它应该成为你团队的基础地图资产。我在维护过程中养成了三个固定习惯随着时间和项目积累这些习惯帮我避开了很多后续麻烦。第一个习惯是解压后先跑校验脚本再入库。校验逻辑很简单遍历全部 feature检查 adcode 是否重复、是否都能匹配行政区划代码的位数规则、每个 feature 是否都有 centroid 和 center、childrenNum 与实际子域 feature 数量是否一致。跑一遍只需要几秒钟但能把数据文件自身的问题在上游拦下来不会带到业务代码里排查半天。我现在的项目里这个脚本是数据流水线的第一道关卡。第二个习惯是保留版本绝不覆盖更新。行政区划代码每年都会调整有的县改区有的市合并有的新增功能区。每次从 DataV.GeoAtlas 下载新数据后我用年份和来源命名归档比如 geo_2024_from_geoatlas.json而不去覆盖旧文件。地图需求往往是历史回溯型的比如「对比去年各区县的销售数据」如果去年的边界被今年覆盖历史数据就画不回当时的行政区划了。这个坑我印象很深某次因为图省事直接覆盖后面要做同比分析时才发现旧边界已经找不回来只能重新找数据源白白浪费了一整天。第三个习惯是前端永远按需加载不碰全量包。我在项目里维护一份「区划索引表」只有省级和市级的前缀信息前端初始化只加载不含子域的省级轮廓用户点击某个省再通过 adcode 前缀动态加载对应省的含子域 json继续点击某个市再加载该市的区县包。这样用户永远只下载他当前看到的这一层数据首屏轻、交互快后端也不用把几十 MB 的全量包直接暴露给前端。配合浏览器缓存二次访问几乎无感。这三件事听起来都不复杂但最花时间的反而是刚开始的那次存量数据整理。我第一次处理时就是简单地把 rar 解压直接扔给前端结果省级、市级、附注框搅在一起后面改了两轮才清净。现在的流程固定为解压 → 校验 → 过滤 → 拆分 → 按版本入库每一步都有对应脚本兜底换谁来接手都不会出错。希望这个流程也能帮你把这套省市区县 GeoJSON 真正用起来少走几趟我走过的弯路。希望帮到你。本文还有配套的精品资源点击获取