简介:这份资源面向使用 ECharts 做数据可视化的前端开发者与数据分析人员,解决网页端绘制中国地图及省级行政区地图时缺少地理数据文件的问题。压缩包共 35 个 js 文件,约 841KB,以 china.js 为核心,配合各省份地图脚本,覆盖北京、上海、广东、新疆、西藏、港澳台等区域,可直接被 ECharts 加载用于地图渲染。使用时引入对应脚本,将地图类型设为 china 或具体省份,即可配置颜色、标注、交互行为,并支持动态数据更新与动画效果,适用于区域数据分布展示、点击区域获取详情、按省份分组统计等场景。目前已有 5705 人学习下载,说明该资源在实际项目中具备较高参考价值。对于需要快速搭建中国地图可视化页面、又不想自行整理地理数据的开发者,这份文件集合能省去大量前期准备时间,直接投入图表配置与业务逻辑开发。
1. 从一张空白地图说起:china.js 到底解决了什么问题
做过大屏可视化的人大概都经历过这个场景:ECharts 的配置项写好了,series 数据也塞进去了,结果地图区域一片空白,控制台安安静静,什么报错都没有。翻文档才发现,ECharts 5 之后地图数据被拆成了独立资源,不再内置。这时候你需要的就是一份 china.js——它把中国及各省份的地理边界数据以 JavaScript 文件的形式封装好,引入后调用echarts.registerMap()注册,地图就能正常渲染。
这个压缩包里装的就是这套东西:中国全图以及各地(省、自治区、直辖市)的 js 地图文件。它解决的核心问题很单一——让 ECharts 在没有 GeoJSON 在线接口、不方便加载外部 JSON 的环境下,用最直接的方式拿到地图数据。适合做大屏看板、数据可视化后台、离线部署项目的同学,尤其是那些内网环境不能访问外部地图服务的场景。下面我从文件结构、注册机制、实战代码到踩坑排查,把这份资源拆开讲清楚。
2. 拆开压缩包:文件命名规律与 registerMap 注册机制
拿到压缩包先别急着往项目里扔,花两分钟搞清楚里面的文件是怎么组织的,后面能省掉大量「为什么地图出不来」的排查时间。
2.1 文件命名与层级结构
这类 china.js 资源包通常包含两类文件:一个是全国级别的china.js,另外若干是省级单位的 js 文件,命名一般用拼音或拼音缩写,比如beijing.js、guangdong.js、zhejiang.js这种。有些版本还会带市级文件,命名规则类似guangdong-shenzhen.js或者直接用行政区划代码。
文件内部的结构基本一致,核心是一个 GeoJSON 对象赋值给某个变量,或者直接调用注册函数。典型形态长这样:
// china.js 内部结构示意(不同版本写法略有差异) (function (root, factory) { if (typeof define === 'function' && define.amd) { define(['exports'], factory); } else if (typeof exports === 'object') { factory(exports); } else { factory((root.echarts = root.echarts || {})); } })(this, function (exports) { // 核心:GeoJSON 格式的地理边界数据 var geoJson = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: { name: '北京', // 这个 name 字段是关键,series 里 name 要对应 cp: [116.405285, 39.904989] // 中心点坐标,部分版本有 }, geometry: { type: 'MultiPolygon', coordinates: [/* 边界坐标数组 */] } } // ... 其余省份 ] }; exports.geoJson = geoJson; });这里有个细节值得注意:properties.name字段决定了地图区域的显示名称,也是 series 数据里name匹配的依据。如果你发现数据明明有、地图上却不显示颜色,八成是这里的 name 和你 series 里的 name 对不上——比如一个是「北京」一个是「北京市」。
2.2 registerMap 的注册流程
ECharts 使用地图的标准流程分三步:引入地图文件、注册地图、配置 geo 或 map series。注册这一步是很多人卡住的地方,因为 ECharts 5 和 4 的写法有差异。
// 方式一:script 标签直接引入(适合传统页面) // <script src="./js/china.js"></script> // <script src="./js/beijing.js"></script> // 注册全国地图,'china' 是自定义的 mapName,后面 geo.map 要用这个名字 echarts.registerMap('china', chinaGeoJson); // 注册省级地图 echarts.registerMap('beijing', beijingGeoJson); // 方式二:模块化引入(适合 webpack/vite 项目) import * as echarts from 'echarts'; import chinaJson from './js/china.js'; echarts.registerMap('china', chinaJson);参数说明:registerMap第一个参数是地图名称,随便起但必须和后续配置里的map或geo.map一致;第二个参数是 GeoJSON 对象。如果你引入的 js 文件是 UMD 格式,全局变量名可能是chinaGeoJson也可能是别的,得打开文件确认一下导出的变量名,这个没有统一标准,是踩坑高发区。
提示:ECharts 5 中
registerMap必须在图表初始化之前调用,否则地图区域渲染不出来。放在echarts.init()之前是最稳妥的。
3. 从零跑通一张中国地图:配置项、数据绑定与交互
注册完地图只是第一步,真正让地图「活」起来需要配置 geo 组件、series 数据映射和交互事件。这一章给出一套可以直接抄的完整配置。
3.1 最小可运行配置
先跑通一个最简版本,确认地图能出来,再往上叠功能。这样出问题的时候排查范围小。
import * as echarts from 'echarts'; import chinaJson from './js/china.js'; // 注册地图 echarts.registerMap('china', chinaJson); const chart = echarts.init(document.getElementById('map')); const option = { // geo 组件负责地图的底图渲染 geo: { map: 'china', // 对应 registerMap 的第一个参数 roam: true, // 开启缩放和拖拽 zoom: 1.2, // 初始缩放比例,1 是默认大小 center: [104, 36], // 初始中心点经纬度,对准中国中部 label: { show: true, // 显示省份名称 fontSize: 10, color: '#333' }, itemStyle: { areaColor: '#e7f0ff', // 区域填充色 borderColor: '#4a90d9', borderWidth: 1 }, emphasis: { // 鼠标悬浮时的高亮样式 itemStyle: { areaColor: '#ffd666' }, label: { color: '#000', fontWeight: 'bold' } } }, series: [ { type: 'map', map: 'china', // 和 geo.map 保持一致 geoIndex: 0, // 绑定到上面的 geo 组件,避免重复渲染 data: [ { name: '广东', value: 1200 }, { name: '江苏', value: 980 }, { name: '浙江', value: 870 }, { name: '北京', value: 650 } ] } ], visualMap: { min: 0, max: 1500, left: 20, bottom: 20, text: ['高', '低'], inRange: { color: ['#f0f9ff', '#bae0ff', '#4a90d9', '#1d39c4'] }, calculable: true } }; chart.setOption(option);逻辑说明:geo组件负责底图,series里的type: 'map'负责数据着色。两者通过geoIndex关联,如果不写geoIndex,ECharts 会自己再渲染一层地图,导致边界线重叠、性能浪费。visualMap把数值映射到颜色区间,这是数据可视化的核心——数值越大颜色越深。
参数上最容易调错的是center和zoom。center是经纬度数组,中国的地理中心大约在[104, 36]附近;zoom大于 1 放大、小于 1 缩小。大屏场景下通常需要根据屏幕分辨率微调这两个值,没有万能参数。
3.2 省级地图下钻与数据联动
全国地图看完了,下一步往往是点击某个省份下钻到省级地图。这需要提前把省级 js 文件也注册好,然后在点击事件里切换。
// 提前注册需要下钻的省份 import beijingJson from './js/beijing.js'; import guangdongJson from './js/guangdong.js'; echarts.registerMap('beijing', beijingJson); echarts.registerMap('guangdong', guangdongJson); // 点击事件:根据点击的省份名称切换地图 chart.on('click', function (params) { const provinceMap = { '北京': 'beijing', '广东': 'guangdong' }; const mapName = provinceMap[params.name]; if (!mapName) return; // 没有对应地图文件就忽略 chart.setOption({ geo: { map: mapName, zoom: 1.1, center: undefined }, series: [{ type: 'map', map: mapName, geoIndex: 0, data: getProvinceData(params.name) // 换成该省的数据 }] }); }); // 返回全国:加一个按钮触发 function backToChina() { chart.setOption({ geo: { map: 'china', zoom: 1.2, center: [104, 36] }, series: [{ type: 'map', map: 'china', geoIndex: 0, data: nationalData }] }); }这里的关键点是:切换地图时center要重置。省级地图的经纬度范围跟全国不一样,如果沿用全国的 center,地图会偏到看不见的地方。我一般会在切换时把center设为undefined,让 ECharts 自动计算合适的中心点,省去手动调坐标的麻烦。
注意:省级 js 文件的
properties.name通常是市级名称(如「深圳」「广州」),和全国地图里的省级名称层级不同。做数据绑定时要确认你的数据粒度跟地图文件匹配。
4. 避坑与排查:地图不显示、名称对不上、打包报错
这一章记录几个我在实际项目里反复遇到、也看到别人反复问的问题。每条按「现象 → 原因 → 解决」来写,遇到对应情况直接对号入座。
4.1 地图区域一片空白,控制台无报错
现象:页面加载了,容器有宽高,但地图区域什么都不显示,控制台也没有红色报错。
原因:最常见的是registerMap没执行或者执行时机不对。ECharts 5 里如果地图没注册就setOption,它不会报错,只是静默地不渲染。另一个可能是容器div的高度为 0——ECharts 需要一个有实际尺寸的容器。
解决:先在setOption之前打印一下echarts.getMap('china'),如果返回undefined说明没注册成功。检查 js 文件是否正确引入、全局变量名是否对得上。容器高度用 CSS 显式设置,比如height: 600px,不要依赖父元素的自动撑开。
4.2 数据有值但区域不着色
现象:series 的 data 数组里明明有数据,visualMap 也配了,但地图上所有区域颜色一样,没有深浅区分。
原因:series.data里的name和 GeoJSON 里properties.name不一致。比如地图文件里写的是「广西」,你数据里写的是「广西壮族自治区」;或者地图里是「新疆」,你写的是「新疆维吾尔自治区」。这种全称和简称的差异是最高频的坑。
解决:打开 china.js 文件,搜索properties里的name字段,把所有名称列出来,然后拿你的数据去比对。如果数据源名称改不了,就在中间加一层映射:
// 名称映射表:把数据源的名称转成地图文件的名称 const nameMap = { '广西壮族自治区': '广西', '新疆维吾尔自治区': '新疆', '内蒙古自治区': '内蒙古', '宁夏回族自治区': '宁夏', '西藏自治区': '西藏' }; const seriesData = rawData.map(item => ({ name: nameMap[item.name] || item.name, value: item.value }));4.3 webpack/vite 打包后地图丢失
现象:开发环境地图正常,npm run build之后部署到服务器,地图区域空白。
原因:js 地图文件通常是 UMD 格式,在模块化打包时可能被 tree-shaking 摇掉,或者全局变量在严格模式下挂载失败。
解决:不要用import直接引入 UMD 格式的地图文件,改用require或者在入口文件里用 script 标签引入。如果必须用 import,确认导出方式:
// 如果 china.js 是 UMD 格式,这样引入更稳 const chinaJson = require('./js/china.js'); // 或者 import chinaJson from './js/china.js'; // 打印确认拿到的是 GeoJSON 对象而不是 undefined console.log('地图数据类型:', chinaJson && chinaJson.type);如果打印出来是undefined,说明模块导出方式不匹配,需要在 vite 配置里加optimizeDeps.include或者改用静态资源方式加载。
4.4 地图边界线重叠、渲染卡顿
现象:地图上省界线看起来有重影,或者拖拽缩放时明显卡顿。
原因:同时配了geo组件和series.type: 'map'但没有用geoIndex关联,ECharts 渲染了两层地图。数据量大时性能开销翻倍。
解决:series 里加上geoIndex: 0,让它复用 geo 组件的底图。如果不需要 geo 组件的额外功能(比如 roam 缩放),也可以只保留 series 的 map 类型,去掉 geo 配置。
4.5 省级地图下钻后数据不刷新
现象:点击省份切换地图了,但颜色还是上一个省的数据。
原因:setOption默认是合并模式,series 的 data 如果没有完全替换,旧数据会残留。
解决:切换地图时用setOption(option, true)第二个参数传true表示不合并、完全替换;或者用chart.clear()先清空再setOption。我一般用前者,更简洁。
5. 进阶技巧:地图数据裁剪、自定义区域与性能优化
基础功能跑通之后,实际项目里往往还有更细的需求。这一章说几个我踩过坑之后总结出来的技巧。
5.1 用 geoJSON 裁剪只保留目标区域
有时候你不需要全国地图,只想展示某几个省。与其加载完整 china.js 再隐藏其他区域,不如直接裁剪 GeoJSON,减少数据量。
// 从全国 GeoJSON 中筛选出指定省份 function filterGeoJson(fullGeoJson, targetNames) { return { type: 'FeatureCollection', features: fullGeoJson.features.filter(feature => targetNames.includes(feature.properties.name) ) }; } // 只保留华东几个省 const eastChina = filterGeoJson(chinaJson, ['上海', '江苏', '浙江', '安徽', '福建', '江西', '山东']); echarts.registerMap('east-china', eastChina);这样做的好处是渲染的数据量小了,缩放拖拽更流畅。缺点是裁剪后的地图边界不完整,视觉上可能不好看,需要根据实际场景权衡。
5.2 自定义区域合并
有些业务场景需要把几个省合并成一个「大区」来展示,比如「华东区」「华南区」。ECharts 本身不支持直接合并,但可以通过给多个区域设置相同的areaColor来模拟,或者在 GeoJSON 层面做几何合并。
// 方案一:视觉合并,给同区域设置相同颜色 const regionColorMap = { '华东': ['上海', '江苏', '浙江', '安徽'], '华南': ['广东', '广西', '海南', '福建'] }; // 在 series data 里给同区域的省份赋相同的分组值 // 然后 visualMap 按分组着色方案二需要用到几何库做多边形合并,复杂度高,一般项目用视觉合并就够了。
5.3 大数据量下的渲染优化
当数据点很多、或者需要频繁更新时,地图渲染可能成为瓶颈。几个实用的优化手段:
| 优化项 | 做法 | 效果 |
|---|---|---|
| 关闭标签 | label.show: false | 减少文字渲染开销 |
| 降低边框精度 | 使用简化版 GeoJSON | 减少顶点数量 |
| 关闭动画 | animation: false | 避免频繁重绘 |
| 按需渲染 | chart.setOption(option, { notMerge: true }) | 避免旧数据残留 |
| 使用 canvas | 默认渲染器,大数据量优于 svg | 提升帧率 |
我一般会在数据量超过 500 个区域时关掉 label 和 animation,肉眼几乎看不出差别,但流畅度提升明显。
5.4 验证地图数据完整性的方法
最后说一个我每次拿到新的地图 js 文件都会做的检查:打印出所有区域的名称列表,确认没有缺失。
// 检查地图包含哪些区域 const mapData = echarts.getMap('china'); if (mapData) { const regions = mapData.geoJson.features.map(f => f.properties.name); console.log('包含区域数量:', regions.length); console.log('区域列表:', regions.join(', ')); } else { console.error('地图未注册成功'); }这个习惯帮我省过好几次事——有一次拿到的地图文件少了两个省,数据怎么都对不上,打印出来一看就发现了。从那以后我每次引入新的地图文件都强制走一遍这个检查,确认区域数量和名称列表没问题再往下做。
希望帮到你。
本文还有配套的精品资源,点击获取