ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ECharts 5中国地图china.json获取与注册实战:解决白屏与数据匹配难题

ECharts 5中国地图china.json获取与注册实战:解决白屏与数据匹配难题 简介面向需要绘制中国地图的ECharts开发者这份地理JSON数据包内含全国省份与地区的精确边界坐标可直接接入地图组件或地理坐标系用于二维/三维地图、飞线动画等可视化场景。压缩包仅1个JSON文件大小43KB体积小巧加载迅速遵循通用地理JSON规范开发者可直接引用该数据文件无需额外转换便可与地图系列、地理组件配合实现数据绑定、悬停提示和区域下钻等交互。目前已有2206人学习下载特别适合构建数据大屏、地理分布展示或自定义地图功能的项目。资源免去了开发者自行爬取或整理行政边界经纬度的过程拿到即可使用既支持平面地图上的数值映射也支持ECharts 5.0的三维地图效果并可结合飞线动画展示城市间路径。整体覆盖全国省份数据精度高是地图类可视化开发的实用基础数据。 如果你用 ECharts 画中国地图第一件事就是搞清楚 china.json 从哪来。很多新手以为 new 一个 chart然后 series.type 写成 map 就能渲染出中国地图但实际跑起来九成是白屏控制台还会甩一句 Map china not exists。原因很简单ECharts 5 之后官方不再内置地图数据你需要自己准备一份 GeoJSON 文件再用registerMap注册进去。这篇笔记就围绕 china.json 这个文件讲清楚它是什么、怎么拿、怎么用以及我在多个项目里踩过的那些坑。后半部分也会带过 echarts-gl 做 3D 地图和 visualMap 分段设置的常见需求。无论你是刚开始接触地图组件还是已经在 Vue、UniApp 里集成过 ECharts这里的内容应该都能直接帮上忙。1. china.json 到底是什么为什么项目里绕不开它1.1 ECharts 5 之后地图数据不再内置在 ECharts 4 及以前的版本里node_modules/echarts/map/json目录下是能直接找到 china.json 的。那时的开发体验很省事引入 ECharts 后也不关心地图数据反正包里面带了。但从 ECharts 5 开始官方把这个目录从包里移除了type: map系列和geo组件都不再内置任何底图。官方希望开发者通过registerMap显式注册地理数据这样地图数据的更新、裁剪、压缩都可以由业务自己控制。对项目来说好处是打包体积变小坏处就是“少了一个文件整个地图就白屏”的坑变多了。1.2 GeoJSON 结构里只需要关注三个东西china.json 的本质是一份符合 GeoJSON 规范的 JSON 文件。ECharts 拿到之后会把里面的坐标点转换成画布上的路径。我们不需要把 GeoJSON 规范全部搞懂但至少要理解三部分最外层通常是FeatureCollection表示这是一个要素集合。features数组里的每一项代表一个区域比如一个省。每个 feature 的properties.name是区域的名称properties.adcode通常是行政编码geometry.coordinates是绘制边界用的坐标数组。ECharts 在渲染时主要靠properties.name和data里的name做映射。如果你拿到一份 json却发现区域名称对不上或者properties里没有name那么地图大概率是能显示轮廓但颜色和数值全部匹配不上。我一般会先跑一行代码把名称全打出来console.log(chinaJson.features.map(f f.properties.name));这样一眼就能看出数据源里到底叫什么名字后面写 data 的时候不容易错。1.3 一份 china.json 能支撑哪些玩法很多人以为 china.json 只用来画一张静态的中国地图其实它的用途远不止这些。基于同一份 GeoJSON 注册出来的地图你可以做省份数值地图、城市打点、3D 地形展示、数据钻取等。常见组合包括series-map展示各省份的指标数据用颜色深浅表达大小。geo组件作为坐标系叠加scatter散点图实现“给某些市标记数量”的效果。echarts-gl里的geo3D配合scatter3D把地图变成立体场景。配合visualMap.pieces精确控制图例分段解决“9 段变 10 段”这类需求。所以一个干净、稳定、命名规范的 china.json是所有地图可视化的地基。2. 获取 china.json 的几种靠谱渠道2.1 推荐阿里云 DataV GeoAtlas 区域选择器目前我最常用的是阿里云 DataV 的 GeoAtlas 区域选择器地址在https://datav.aliyun.com/portal/school/atlas/area_selector。进入页面后左侧选择“中国”右侧就能看到对应的 GeoJSON 输出直接复制保存为china.json即可。这个数据源有几个优点数据更新相对及时结构干净properties里带了name、adcode等字段方便做编码映射。而且它不止能下载全国地图还可以按省、按市精确下载对应的 GeoJSON。比如你只需要广东省的数据直接在区域选择器里点“广东省”下载下来的就是一个省级的 FeatureCollection可以直接注册成guangdong地图。有一点要注意GeoAtlas 上同一份数据也可能更新建议下载后看一眼文件大小和名称字段。如果发现数据版本比较旧或者行政区划和业务需求不一致再换其他数据源。2.2 从旧版 echarts 包或公共 CDN 提取如果只是做本地 demo或者项目比较着急还有一个快速方案安装echarts4然后把node_modules/echarts/map/json/china.json复制出来。npm i echarts4 --save-dev cp node_modules/echarts/map/json/china.json ./src/assets/geo/china.json这个方案胜在快但不建议直接用于正式项目。原因是老版本数据可能和当前行政区划不一致而且很多公共 CDN 上流传的 china.json 来源不明你无法确定文件有没有被改过坐标、改过名称一旦地图展示出问题排查成本会很高。我的建议是可以用它做临时验证线上环境还是换成官方或可信渠道的数据源。2.3 按需裁切子区域 GeoJSON有时候手头只有一份全国地图数据但业务只需要其中几个省份这时不需要再重新找文件可以直接对全国数据做过滤。GeoJSON 的features数组对应各个区域只要把不想要的 feature 过滤掉剩下的结构依然是合法的 FeatureCollection。下面是一个简单的 Python 脚本保留指定省份import json with open(china.json, encodingutf-8) as f: data json.load(f) target [广东省, 江苏省] data[features] [ feat for feat in data[features] if feat[properties][name] in target ] with open(subset.json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse)这个脚本没有改动外层结构所以过滤后的文件还是能被 ECharts 正常识别。如果你需要单个省或市的完整边界更推荐直接用 DataV 区域选择器下载对应层级的 GeoJSON而不是自己从全国数据里裁因为后者容易把相邻区域的边界细节弄丢。3. 在 ECharts 中正确接入 china.json3.1 注册地图并绘制基础地图接入流程其实很固定先importGeoJSON再registerMap最后在配置项里指定map名称。以 Vite ECharts 5 为例import * as echarts from echarts; import chinaJson from ./assets/geo/china.json; echarts.registerMap(china, chinaJson); const chart echarts.init(document.getElementById(map)); chart.setOption({ geo: { map: china, roam: true, itemStyle: { areaColor: #f2f2f2, borderColor: #666 } } });如果只需要展示省份数值可以用series-mapchart.setOption({ series: [{ type: map, map: china, data: [ { name: 广东, value: 120 }, { name: 江苏, value: 88 } ], label: { show: true }, emphasis: { label: { color: #333 } } }] });这里最容易踩的坑是注册名不一致。registerMap(china, chinaJson)里写的名字必须和配置项里的map: china完全一样否则控制台会直接报Map china not exists。3.2 用 visualMap 控制图例分段默认情况下给series-map配一个visualMap就能自动分 5 段但自动分段经常把数据切成奇怪的小数比如 0-12.4、12.4-24.8。业务上我们更希望分段是整数且数量可控。这时候用visualMap.pieces是最直接的方案。很多人在搜“9 段图变 10 段图”其实就是一个精确配置区间的问题visualMap: { type: piecewise, pieces: [ { gt: 0, lte: 10 }, { gt: 10, lte: 20 }, { gt: 20, lte: 30 }, { gt: 30, lte: 40 }, { gt: 40, lte: 50 }, { gt: 50, lte: 60 }, { gt: 60, lte: 70 }, { gt: 70, lte: 80 }, { gt: 80, lte: 90 }, { gt: 90, lte: 100 } ], inRange: { color: [#e0f3f8, #abd9e9, #74add1, #4575b4, #313695] } }这里写死了 10 个区间如果不想要最后一段去掉一个就是 9 段。要注意gt表示大于、lte表示小于等于gte表示大于等于、lt表示小于。区间写重叠会导致图例里出现多个同样的数据值写漏段则会出现某个数据范围没有颜色。3.3 给某些城市标记数量“在地图上给某些市标记数量”是很常见的需求但不一定需要市级 GeoJSON。如果只是把广州、长沙这种城市当成点标出来叠加一个scatter散点系列就行series: [{ type: scatter, coordinateSystem: geo, data: [ { name: 广州, value: [113.2644, 23.1291, 320] }, { name: 长沙, value: [112.9388, 28.2282, 76] } ], symbolSize: function (val) { return Math.max(4, Math.sqrt(val[2]) * 2); }, label: { show: true, formatter: function (p) { return p.name : p.value[2]; }, position: right }, itemStyle: { color: #ff6600 } }]这样既能看到城市位置又能在点旁边展示数量。城市经纬度可以从坐标拾取器获取但要注意不同地图坐标系存在偏差。如果业务系统已经有城市经纬度优先用业务数据因为那通常和你的业务口径是一致的。如果你的目标不是“打点”而是让某些城市所在区域也按数值填色那就需要下载市级 GeoJSON 并注册成新的地图。比如echarts.registerMap(guangdong, guangdongJson); chart.setOption({ series: [{ type: map, map: guangdong, data: [ { name: 广州市, value: 300 }, { name: 深圳市, value: 500 } ] }] });这种方式适合做下钻分析。3.4 加一个 3D 版本geo3D scatter3D如果你觉得平面地图不够直观可以引入echarts-gl做 3D 效果。npm i echarts-gl然后在代码里引入import echarts-gl; const chart3d echarts.init(document.getElementById(map3d)); chart3d.setOption({ geo3D: { map: china, roam: true, itemStyle: { color: #aaa, opacity: 0.9 }, label: { show: false } }, series: [{ type: scatter3D, coordinateSystem: geo3D, data: [ { name: 北京, value: [116.4074, 39.9042, 100] } ], symbolSize: 8, itemStyle: { color: #ff6600 } }] });现在的echarts-gl常用geo3D组件来展示 3D 地图早期版本里的map3D写法在新项目里不推荐。看到老博客还在用map3D时不要直接照抄先确认对方用的 ECharts-gl 版本。另外3D 渲染比普通 canvas 更耗性能移动端要慎重数据量大的时候建议降级回平面地图。4. 接入过程中最常见的坑与排查方法4.1 地图不显示控制台报 Map china not exists这个错误大概率是以下三种原因之一一是没有调registerMap就直接setOption二是注册名和配置名不一致三是异步加载 json 还没返回就执行了setOption。正确的异步加载应该是fetch(/geo/china.json) .then(res res.json()) .then(chinaJson { echarts.registerMap(china, chinaJson); chart.setOption({ geo: { map: china } }); });如果你用了async/await也务必保证registerMap在setOption之前完成。4.2 地图被压成长方形或者显示成“全球地图”最常见的原因是容器只有宽度没有高度或者高度设成了 0。地图组件和普通图表不一样容器高度为 0 时不会报错但地图会被压缩成一条线或一个长方形。给地图容器一个明确高度是最简单的解决办法#map { width: 100%; height: 600px; }还有一种情况是误用了type: world或者把layoutCenter/layoutSize配置得过于极端导致区域被拉伸。遇到这种问题可以先删掉 geo 里所有 layout 相关配置只保留map和roam看地图是否能恢复正常。4.3 Vue 3 项目里 ECharts 实例出现 “raw” 字样这个坑我在 Vue 3 项目里遇到过。用ref保存图表示例模板里又不小心把实例直接写进插值表达式页面/控制台就会显示类似{_raw: ...}的奇怪内容。这不是 ECharts 坏了而是 Vue 的响应式代理把实例对象内部属性列出来了。正确做法是使用shallowRef配合markRawimport { shallowRef, markRaw, onMounted, onBeforeUnmount } from vue; const chartInstance shallowRef(null); const mapEl ref(null); onMounted(() { chartInstance.value markRaw(echarts.init(mapEl.value)); chartInstance.value.setOption({ /* ... */ }); }); onBeforeUnmount(() { chartInstance.value chartInstance.value.dispose(); });模板里只放div refmapEl styleheight:600px/div不要在插值表达式里输出 chart 对象。Vue 2 项目也一样尽量不要把 chart 实例放进 data 响应式系统里用this.chart chart会更安全。4.4 china.json 体积太大首屏白屏很久完整的全国地图数据可能几百 KB 甚至更大直接打包会让首屏压力变大。常规优化方法有几个用 mapshaper 之类的工具降低坐标精度。只在需要时异步加载地图数据而不是首屏同步引入。如果页面只展示特定省市只下载对应省市的 GeoJSON。如果部署在 Nginx给 json 开启 gzip。一个简单的 mapshaper 简化命令npx mapshaper china.json -simplify 10% -o china_simplified.json简化率不是越小越好10% 只是一个起点。简化后一定要肉眼验证一遍省份边界尤其是一些形状复杂的省份简化太狠会显示成多边形拼凑。4.5 省份数据匹配不上没有颜色如果地图能显示但某个省份没有按数据填色通常就是name对不上。GeoJSON 里是“广东省”你接口里返回“广东”ECharts 就匹配不到。解决方案是先把数据源的name全部打印出来再写一个映射表const nameMap { 广东: 广东省, 江苏: 江苏省 }; const mapData rawData.map(item ({ name: nameMap[item.province] || item.province, value: item.value }));如果后端返回的是adcode也可以直接用properties.adcode和接口编码做关联比匹配中文名更稳。4.6 visualMap 分段数量和预期不符自动分段是由 ECharts 根据数据最小值和最大值计算的段数往往不是你期望的 5 段、9 段或 10 段。要精确控制分段就用上面提到的pieces。配置时注意区间写法gt表示大于、gte表示大于等于、lt表示小于、lte表示小于等于。如果你配置了 10 段但图例只显示 9 段大概率是某个区间把最小值或最大值排除掉了检查一下边界值是否在区间内。5. 给新接手地图项目的同行的两个建议5.1 数据源与版本管理我一般会把 china.json 的下载日期、数据来源、是否简化过这些信息记在 README 或代码注释里不然三个月后再看项目根本不知道这份 GeoJSON 是从哪里来的、行政区划是哪个版本的。更新地图数据时尽量做一次前后对比重点看区域名称是否变化adcode 是否变化以及边界文件大小有没有明显变化。尽量不要在业务代码里手动改 GeoJSON 的name和coordinates宁可多写一层映射也不要去动底图文件否则后面数据更新时会很难对账。5.2 渲染与发布时的检查清单地图类可视化对容器尺寸、加载时序和数据一致性都很敏感。切换 tab 或窗口大小变化时记得调用chart.resize()如果容器一开始是隐藏的等显示后再init否则地图宽度会计算错误。接口返回的地区维度尽量统一到一套行政编码体系再转成 GeoJSON 的name去匹配避免“看似是同一个地方实际有两个名字”这种低级事故。如果项目要对外发布地图数据尽量使用权威渠道的最新版本并在发布前做一次走查重点看区域显示、名称展示和 tooltip 是否正常。地图数据属于基础地理信息底图的权威性直接影响展示效果这一点值得花时间认真核对。实际项目中地图组件并不难难的是把数据准备、版本管理和边界情况处理得足够稳。希望这篇笔记能帮你少踩几个坑。本文还有配套的精品资源点击获取
返回列表