ARTICLE DETAIL

资讯详情

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

ECharts 5.0中国地图实战:从GeoJSON注册到数据下钻全攻略

ECharts 5.0中国地图实战:从GeoJSON注册到数据下钻全攻略 简介ECharts 5.0 附带 china.js 的中国地图可视化资源包面向需要在前端项目中展示地理数据的 JavaScript 开发者可快速实现省份、城市级的区域分布、销售额统计等地图可视化应用。压缩包共 1313 个文件其中包含 675 个 JavaScript 文件涵盖 ECharts 核心库、扩展模块与地图数据570 个 TypeScript 类型声明方便在 TypeScript 工程中获得智能提示还有 JSON 配置、地图映射文件及说明文档等整体约 11.77MB。已有 497 人学习下载适合中高级前端开发者借鉴。资源内不仅提供常用构建版本还将 china.js 中国地图数据与配套配置整合在一起开发者可以直接调用 ECharts 5.0 的增强动画、性能优化和响应式布局能力自由绑定数据并自定义地图样式同时可利用新增的树图、力导向图等图表类型以及更友好的 API 配置从基础统计图表平滑过渡到复杂地理可视化项目提升数据展示效率。1. 为什么ECharts 5.0不能直接配china.js了先聊个真实的场景去年公司要做一个疫情数据大屏我兴冲冲地拉了个ECharts 5.0的项目按着几年前收藏的教程引入china.js结果控制台直接给我报了个大红叉——Map china not exists。我当时第一反应是文件路径写错了折腾了半天才发现不是我的问题是这种方式在5.0版本里已经走不通了。这个事儿得从ECharts的版本演进说起。早期的ECharts 2.x和3.x时代官方确实把中国地图还有世界地图、各省地图的GeoJSON数据直接内置在发布包里你只要引入echarts后再引入一个china.js地图就能用。但后来官方考虑到包体积和按需加载的问题从4.9版本开始就不再默认内置地图数据了到了5.0更是彻底把地图数据从核心包里剥离出去。也就是说你现在的ECharts 5.0核心包里只有图表组件和渲染器地图数据需要你自己下载GeoJSON再通过registerMap手动注册进去。所以那些流传很广的“echarts china.js”教程大多数是给3.x版本写的直接搬到5.0项目里不报错才怪。另外一个坑是老版本的china.js本身是个UMD包里面写的是echarts.registerMap(china, {...})这种格式如果你的项目里用的是ES Module的引入方式import * as echarts from echarts老china.js里的echarts变量根本没定义自然也就注册不了。就算你运气好绕过了报错老china.js里的GeoJSON数据也是很多年前的部分地区边界和现在的实际边界有出入画出来可能闹出乌龙。所以结论很清楚ECharts 5.0项目里不要再折腾china.js了正确姿势是用GeoJSON来注册地图。简单整理一下版本差异方便大家对照版本地图数据方式是否内置中国地图推荐用法ECharts 2.x / 3.x内置配合china.js直接使用是直接引入china.js即可ECharts 4.9不再内置需下载GeoJSON注册否registerMap手动注册ECharts 5.0不再内置需下载GeoJSON注册否fetch加载GeoJSON registerMap或构建时打包2. 前期准备GeoJSON数据从哪里拿既然地图数据要自己搞第一步就是选数据源。我试过几个渠道简单说下体验。最省心的是阿里云DataV的GeoJSON数据接口直接通过URL就能拿到中国地图的GeoJSONhttps://geo.datav.aliyun.com/areas_v3/bound/100000_full.json这个接口返回的是标准GeoJSON格式包含全国所有省级行政区域的边界数据也比较新。100000是国家行政区划代码全国地图就是它如果要拿到某个省的地图比如广东省440000把URL换成https://geo.datav.aliyun.com/areas_v3/bound/440000_full.json就能拿到广东省的地图数据。这个接口现在非常常用国内很多数据可视化项目都在用稳定性我还是比较放心的。不过需要注意一点这个接口返回的数据是全量版文件体积大约在600KB到1MB之间如果你的项目对首屏性能要求高建议自己再做一次数据简化下文会讲。除了DataV还可以从ECharts官方GitHub仓库的echarts/map/json/china.json目录下找到官方维护的地图数据或者从一些第三方GIS数据平台下载但那些平台的数据质量参差不齐命名规范和坐标精度都可能有问题。我个人建议优先用DataV或官方维护的版本数据边界准省的后面被用户吐槽。另外地图数据还有个非常关键的细节不要直接用浏览器双击打开HTML文件来调试。因为用fetch加载本地GeoJSON文件时file://协议下会有跨域限制控制台会报CORS错误。正确姿势是在本地起一个静态服务器比如用VS Code的Live Server插件或者直接命令行起个Node静态服务npx serve .然后在浏览器里通过http://localhost:3000访问这样地图数据才能正常加载。3. 实操从注册地图到渲染一张完整中国地图铺垫了这么多现在进入正题。我用一个最简单的例子带大家从零跑通一张中国地图。先建一个HTML文件结构大概是这样的!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleECharts 5.0 中国地图示例/title script srchttps://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js/script style #map { width: 100%; height: 600px; } /style /head body div idmap/div script // 核心代码 /script /body /html先引入ECharts 5.0的CDN文件版本号可以根据实际情况调整。然后写核心逻辑分三步走第一步初始化图表实例const chart echarts.init(document.getElementById(map));第二步加载GeoJSON并注册地图fetch(https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json) .then(response response.json()) .then(geoJson { echarts.registerMap(china, geoJson); // 注册完成后才能用这个地图名去初始化图表配置 renderMap(); }) .catch(err { console.error(地图数据加载失败, err); });关键就在registerMap这个方法第一个参数是给地图起的名字第二个是GeoJSON对象。注册之后图表配置里的geo或series-map组件就能通过map: china来引用了。第三步配置图表渲染function renderMap() { chart.setOption({ // 这里先用geo组件来展示基础地图 geo: { map: china, roam: true, itemStyle: { areaColor: #e0e0e0, borderColor: #333 }, label: { show: true, fontSize: 10 } } }); }到这里一张能缩放、拖拽的中国地图已经渲染出来了。roam: true是开启鼠标缩放和平移这个配置在地图场景里非常常用。label.show控制是否显示省份名称如果数据点比较多、地图也比较小的时候建议把字号调小或者干脆关掉不然画面会很挤。如果你是先用package.json管理依赖的Vue或者React项目写法也差不多只是引入方式变成了ES Moduleimport * as echarts from echarts; import chinaJson from /assets/china.json; echarts.registerMap(china, chinaJson);这也是为什么我前面强调要下载GeoJSON文件到本地的原因之一——在前端工程化项目里把地图数据下载到本地assets目录打包时直接一起打进去运行时不依赖外部接口稳定性和首屏体验都有保障。4. 数据对接让地图“说话”的关键一步地图空壳子肯定不够用做数据可视化的核心是让颜色、数字和地理区域产生联动。接下来我完整演示一下如何把各省的数据绑定到地图上这也是实际项目里最常用的场景。假如我现在手头有一份“2024年各省销售额”的数据const salesData [ { name: 广东, value: 89234 }, { name: 江苏, value: 76321 }, { name: 山东, value: 65432 }, { name: 浙江, value: 58764 }, { name: 河南, value: 49210 }, // ...更多省份 ];然后用series里的map类型来渲染同时配置visualMap组件让颜色根据数值变化chart.setOption({ tooltip: { trigger: item, formatter: function(params) { if (params.value) { return params.name params.value.toLocaleString() 万; } return params.name 暂无数据; } }, visualMap: { min: 0, max: 100000, left: left, top: bottom, text: [高, 低], inRange: { // 按数值从小到大颜色从浅到深 color: [#e8f0ff, #a6c8ff, #6a9ef5, #3d7ad6, #1f4e9e] } }, series: [{ type: map, map: china, roam: true, label: { show: true, fontSize: 10 }, data: salesData }] });这段配置里有几个地方值得展开说说。关于geo和series-map的区别。如果你只需要展示地图背景不联动数据用geo组件就够了性能更好。但如果你要让省份根据数据值动态填色、悬停显示数据、点击触发事件就必须用series类型为map的配置。两者也可以混用比如用geo显示地图轮廓再用series上的map叠加数据层geoIndex参数关联起来可以做更复杂的效果。新手一开始不需要搞那么复杂掌握series-map就能覆盖大多数业务需求。关于visualMap的min和max。这两个值不要写死最好根据实际数据动态计算。比如const values salesData.map(item item.value); const min Math.min(...values); const max Math.max(...values);然后把计算出来的min和max塞给visualMap。如果写死了0~100000而实际数据只有几千颜色梯度就拉不开图上看起来像全是一个色等于白做了。关于数据名称的对齐问题。GeoJSON里每个区域都有一个name字段比如“广东省”“北京市”而你的业务数据里可能写的是“广东”“北京”对不上就渲染不出颜色。这时候要么把数据名改成全称要么在配置里加一个nameMap映射。更保险的做法是用数据中的adcode行政区划代码来匹配比如广东的adcode是440000这样最不容易出错。不过series-map默认是按下发名称匹配的所以最简单的日常操作还是确保两边名字一致。做过一次数据对接后后面再做其他区域的地图比如各省、各市基本就是复制粘贴改配置的活。地图可视化真正麻烦的不是写代码而是数据清洗和名称对齐这个我在后面排查章节还会再提到。5. 进阶玩法省份下钻与地图联动地图能填色之后很多项目的下一步就是点击某个省份钻取到省级地图看更细的数据。这个需求在ECharts里怎么做呢我提供一个最常用的思路。先监听地图的点击事件chart.on(click, function(params) { // params.name 就是你点击的那个省份名称比如“广东” // params.componentType 是 series说明点的是数据层 // 找到对应省份的adcode然后加载省级GeoJSON并注册 const adcode getAdcodeByName(params.name); if (adcode) { fetch(https://geo.datav.aliyun.com/areas_v3/bound/${adcode}_full.json) .then(response response.json()) .then(geoJson { echarts.registerMap(params.name, geoJson); // 更新图表配置把map切换成新的省份地图 chart.setOption({ series: [{ map: params.name, // 需要保留现有的data或者其他配置可以配合 spread 参数使用 // 具体看项目逻辑 }] }); }); } });这里有几个细节需要注意。一是getAdcodeByName这种映射关系你可以手动维护一份表格或者从GeoJSON的features里直接用已知数据反查。更省事的方案是直接用params.adcode在DataV的GeoJSON数据里每个feature都自带adcode属性事件回调里能不能直接拿到adcode字段要看渲染的图层情况——如果用series-mapparams.adcode在部分版本里可能拿不到那时再结合自己维护的映射关系即可。二是钻取之后的返回逻辑。你钻到广东省之后需要一个“返回全国”的按钮重新加载全国GeoJSON并setOption。这个功能不难但容易在交互细节上踩坑比如连续快速点击不同省份时上一次的异步请求还没回来这一次的又发出了导致地图错乱。解决办法也很简单用一个requestPending的标志位做防抖请求发出时置为true回来之后置为false如果为true就直接忽略点击事件。我实际做过的下钻接线里最需要花时间的其实是省级以下的往下钻数据。全国的数据可以从DataV拿市、县的GeoJSON、数据指标、名称统一性这些往往需要业务方一起配合才能做好不是纯前端就能搞定的。所以做下钻前一定先确认手上有没有更底层的地图数据和对应数据不然交互做一半卡住了会很被动。6. 常见问题与排查技巧实录这部分直接上一张排查表都是我在实操中真实遇到过的问题按频率排序报错或现象可能原因解决方案Map china not exists地图未注册registerMap没执行成功检查GeoJSON是否加载成功确认registerMap在setOption之前调用地图不显示页面空白容器宽高为0或者GeoJSON加载失败被catch吞掉给容器写死宽高在catch回调里打印错误信息地图显示了但省份没颜色series没有配置data或数据名称和GeoJSON的name对不上给series配置带vvalue的data并检查name名称南海诸岛显示不全或位置不对地图数据不是官方完整版或坐标系概念混淆用DataV、官方下载的GeoJSON这类数据里小地图都处理过缩放在页面上不生效没有设置roam: true在geo或series.map中开启roam所有省份颜色都一样visualMap的min/max范围过大或数据没进来动态计算min/max检查data是否被正确解析另外还有几个比较隐蔽的坑我单独拿出来讲。坑一GeoJSON文件体积导致的加载卡顿。全量的全国地图GeoJSON有接近1MB放在外网或者网络不好的环境下加载会很慢严重的情况地图组件会白屏好几秒。解决办法有两个方向一个是用工具简化GeoJSON比如mapshaper这个在线工具可以把精度降低、节点数减少压缩到200KB左右另一个是把GeoJSON下载到本地打包走构建工具的压缩流程。坑二ECharts 5.0里registerMap的兼容性问题。你在网上搜到的一些GeoJSON是老版本导出的数据格式里面用的是旧的encodeOffsets属性或特殊的坐标计算方式。如果你在注册时发现地图整体错位或者图形错乱大概率是数据格式和当前ECharts版本不兼容。遇到这种情况不要再纠结直接去DataV或官方仓库再下一份最新的GeoJSON几分钟就能解决问题别想花时间去兼容老数据。坑三名称规范化处理。这里再强调一次因为我们做数据对接时几乎每次都要处理这个问题。GeoJSON中的省份名称一般是全称比如“黑龙江省”你如果直接跟业务系统的简称“黑龙江”匹配完美错过什么都显示不出来。我通常的做法是先加载GeoJSON遍历它的features把里面所有的name字段打印出来然后对照业务数据名称写一个nameMap替换配置。这一步走完后面就一路顺畅了。7. 最后再分享一个小细节到了文章末尾我不打算做什么大总结就分享一个这段时间用下来的心得。如果你正在做一个和地理数据有关的项目先把地图的加载方式定下来再动手写业务代码会很省事。我一开始图省事直接在全局引了个老china.js后来换成GeoJSON方案时把所有组件里写死的map: china都检查了一遍有些组件换成了geo背景有些换成了series-map数据层改得那叫一个酸爽。在项目启动时就统一好地图注册的入口文件所有地图组件都从同一个文件里取地图名后边不管是换数据源还是加下钻都会轻松很多。另一个小技巧是如果你做的是全国地图的下钻可以把省、市、县三级的GeoJSON全部下载下来放本地打包的时候一起发布。虽然前期下载数据的过程有点繁琐但上线之后不依赖任何外部地图服务响应速度和稳定性都更可控维护起来心里也有底。ECharts地图这块说来说去其实就是“GeoJSON registerMap”这一套组合拳掌握了核心机制无论数据源怎么换、需求怎么变你都不会慌。希望这篇实战笔记能给你趟平几条弯路。本文还有配套的精品资源点击获取
返回列表