ARTICLE DETAIL

资讯详情

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

ECharts地图可视化全攻略:从GeoJSON注册到数据下钻实战

ECharts地图可视化全攻略:从GeoJSON注册到数据下钻实战 简介这是一份ECharts离线地图数据合集面向需要离线进行地理数据可视化的前端开发者与数据分析师解决官方不再提供完整离线地图下载的痛点。压缩包仅3.87MB收录全国所有省份及地级市地图数据文件以JSON等ECharts支持格式保存按行政区划命名便于直接定位同时附有使用说明文档和map目录介绍加载方式、格式要求与常见问题。目前已有150人学习下载适合用于搭建区域数据看板或地图大屏。借助它可在不联网时调用任意省市地图配合ECharts的geo组件完成数据绑定、颜色映射、悬浮提示与点击交互并可与柱状图、折线图等联动适用于人口、经济、交通等多维度数据的专题分析。资源整体小巧但覆盖完整对离线部署、二次开发和学习实践都很有帮助也因官方不再提供完整离线包而具收藏价值。 上个月接了个数据大屏的活需求里有一条全国各省份销售分布地图。我心想这不是ECharts的看家本领吗翻开官网示例咔咔就抄结果地图区域死活渲染不出来控制台也不报错就是一个白屏。查了一下午才明白ECharts从v5开始砍掉了内置地图数据以前那种引一个china.js就能画地图的用法早就是过去式了现在想显示地图必须先准备一份GeoJSON数据再手动注册。后来在一个叫echarts-all-map.rar的包里翻到了全套地图JSON问题才算解决。这个包在ECharts地图开发圈里流传很广本质就是把常用的中国地图、世界地图、各省市地图数据打包到一起省得开发时到处找数据源。这篇文章就从这类全家桶压缩包说起把ECharts地图可视化的完整链路拆一遍数据从哪来、怎么注册、怎么把业务数据绑上去、实际开发中会踩哪些坑以及地图性能优化和下钻怎么做。1. 为什么ECharts地图非要有这个全家桶压缩包1.1 ECharts v5之后地图数据不再内置先说背景。ECharts在4.x及更早的版本里是自带地图数据的官方包里有china.js、world.js甚至各省市的js文件引入之后直接echarts.registerMap(china, chinaJson)就能用。但v5版本之后官方把这些地图数据全部移除了理由也实在——地图数据维护成本高行政区划经常调整地图边界、名称、编码一直在变官方不可能每更新一次都跟一遍。这就导致一个局面所有用ECharts画地图的开发者都必须自备GeoJSON数据。对做可视化的人来说最折磨人的不是写option配置而是找数据。我见过不少同事卡在这一步官网示例抄得明明白白series: [{ type: map, map: china }]但就是画不出来其实就是没有注册地图数据。1.2 全网地图JSON的坑比你想的多网上的地图数据源看着不少但真正靠谱的没几个。大致分为几类一是阿里云DataV GeoAtlas这个最稳定按adcode直接拉后面讲市级地图时会细说二是GitHub上各种ECharts地图仓库质量参差不齐有的坐标系不对有的边界数据明显有问题用的时候得自己验三是一些旧版ECharts项目的备份里面是4.x时代的地图js格式倒还能用但数据有没有更新没人保证。像echarts-all-map.rar这类包之所以有价值就是帮你把这些杂乱的数据源整合成一份相对可用的数据集合。用的时候不用再到处翻仓库、试错解压出来挑一个注册就行。但我要提醒一句这类包适合开发联调和快速出demo如果是企业生产环境尤其是涉及国内地图展示和测绘合规的场景建议还是通过正规数据渠道获取带审图号的地图数据避免边界问题带来的风险。1.3 解压后第一件事验货拿到任何一个地图包别急着往上接业务代码先验货。我的习惯是三步走第一步随便挑一个JSON文件用JSON.parse跑一遍确认不是损坏文件第二步用在线GeoJSON预览工具打开看地图整体轮廓是否正常特别关注国界、省界这种关键边界有没有明显错误第三步在本地起个最简单的ECharts页面注册后加载一遍确认能渲染出来。验货这一步千万别省。我在一个外包项目里就吃过亏用了别人给的全国地图JSON上线后客户发现某地区边界不对最后只能紧急替换。与其事后救火不如拿到包先花十分钟检查。2. 注册地图的完整链路以及geo和map两套体系的分工2.1 registerMap的三种数据格式选对很关键ECharts的registerMap方法可以接收三种格式的数据GeoJSON、SVG路径、单个区域的GeoJSON。绝大部分场景下用的都是标准的GeoJSON格式也就是一个FeatureCollection对象里面有一堆feature每个feature的properties里有name字段。用法很简单import * as echarts from echarts; import chinaJson from ./map/china.json; echarts.registerMap(china, chinaJson);这里有个细节容易踩坑registerMap的第一个参数是地图名称后面在option里引用的map: china必须和它完全一致大小写都要一样。我见过有人注册时写的是China引用时写china结果怎么都渲染不出来最后排查才发现是名字对不上。至于SVG路径格式和单区域GeoJSON格式日常业务场景用得少这里不展开。你只需要记住从包里拿到的JSON文件十有八九是标准GeoJSON直接注册就能用。2.2 geo是用地图当背景map是让数据上地图ECharts里有两个组件都能显示地图一个是geo组件一个是series-map系列。很多人搞不清它俩的区别其实一句话就能说明白geo是把地图当背景用来定位散点、飞线这类需要地理坐标的图形series-map是把数据塞到地图的每个区域上用颜色深浅表达数值大小。实际开发中两者经常混用。比如我要做一张各省销售额分布图底下用series-map给省份上色同时在全国几个核心城市叠加散点效果这时就可以再加一个geo组件配scatter3D或者普通的scatter。但要注意geo和map同时存在时zoom、center这类地图视野配置要写在map组件里还是geo组件里得理清楚否则会出现地图位置对不上散点的诡异问题。我的建议是以series-map为主时把视野配置写在series-map里以geo为定位层时视野配置写在geo里避免两套配置互相覆盖。2.3 最小可运行的中国地图示例直接给一个能跑的最小示例省得你从零拼配置import * as echarts from echarts; import chinaJson from ./map/china.json; echarts.registerMap(china, chinaJson); const chart echarts.init(document.getElementById(map-container)); chart.setOption({ tooltip: { trigger: item }, visualMap: { min: 0, max: 1000, left: 20, bottom: 20, text: [高, 低] }, series: [{ type: map, map: china, roam: true, label: { show: true }, data: [ { name: 北京, value: 800 }, { name: 上海, value: 650 }, { name: 广东, value: 920 } ] }] });这段代码里roam: true允许用户拖拽和缩放地图大屏场景一般建议关掉防止误操作。label.show控制省份名称是否显示省份多的时候建议关掉只在地图放大时显示否则会很乱。3. 让地图替你说话数据绑定、visualMap与提示框实战3.1 name匹配逻辑地图数据和你业务数据的主键地图之所以能显示不同省份的颜色核心在于数据绑定。ECharts的series-map数据是一个数组数组里每个对象都有一个name和valuename必须和GeoJSON里对应feature的properties.name完全一致才能匹配上。这里就是坑最多的地方。比如GeoJSON里写的是北京市你的业务数据库里写的是北京中间差了一个市字ECharts匹配不到这个区域就不会有任何颜色显示也不会报错。再比如内蒙古自治区有的数据源里写内蒙古有的写内蒙古自治区还有的写内蒙三种叫法对不上直接漏掉。我现在的做法是在数据接入层写一个省份名称归一化映射表把常见的简称、全称、旧称统一映射到GeoJSON里的标准名称上再交给ECharts。比如广东、广东省、粤都映射成广东。这样不管上游数据长什么样到图表这一层名称都是统一的。3.2 visualMap连续型和分段型到底怎么选visualMap是地图可视化的灵魂它把数值映射成颜色。ECharts提供两种模式continuous和piecewise。连续型适合数值平滑分布的场景地图上颜色渐变看起来自然分段型适合把数据分成几个档位比如0到100一个色100到500一个色500以上一个色。分段型有一个很实用的配置叫pieces可以自定义每一档的范围和颜色visualMap: { type: piecewise, pieces: [ { min: 1000, label: 1000以上, color: #b30000 }, { min: 500, max: 1000, label: 500-1000, color: #e34a33 }, { min: 100, max: 500, label: 100-500, color: #fc8d59 }, { min: 0, max: 100, label: 0-100, color: #fed976 } ] }网上经常有人问ECharts地图9段图怎么变10段图其实就是往pieces数组里加一段而已。这里有个经验分段边界重叠时ECharts会报错或者出现数据落入多段的情况所以min和max的边界值要仔细检查保证每段之间不重叠、不遗漏。我习惯把边界写成前闭后开比如{ min: 500, max: 1000 }下一段从{ min: 1000 }开始避免歧义。3.3 tooltip与label大屏上最容易忽略的细节地图的tooltip默认展示的是区域名称和数值但实际项目里通常要显示更多信息。比如销售场景希望鼠标悬停时能看到销售额、订单量、同比涨幅这时就要用formatter手动拼接HTMLtooltip: { trigger: item, formatter: function(params) { var data params.data || {}; return params.name br/销售额 data.value 万br/订单量 (data.orders || 0) 单; } }注意params.data是series里对应的那个数据对象所以在构造data数组时可以多塞几个自定义字段只要name唯一就行tooltip里想展示什么都能取到。label的配置也有讲究。全国地图下省份多label全开就是一团字完全看不清。我的默认配置是全国视角下关掉label下钻到省一级再开同时用labelLayout做防重叠。大屏场景里如果非要显示label可以只显示数值较大的前几个省其余隐藏视觉干净很多。4. 我踩过的六个地图深坑以及完整的排查思路4.1 地图白屏registerMap和setOption的时序问题白屏是最常见的问题而且控制台通常还不报错。我在vue项目里第一次遇到时排查了很久才发现是异步加载JSON的时序问题。GeoJSON文件可能是通过fetch或者import动态加载的如果setOption执行时registerMap还没执行完ECharts拿到一个不存在的地图名就会静默地不渲染。排查思路很简单在chart.setOption之前加一行console.log(echarts.getMap(china))看看注册结果是否为undefined。如果是说明地图还没注册成功需要把setOption挪到JSON加载完成后的回调里。现在ES modules的场景下直接import chinaJson from ./map/china.json顶层同步执行一般没有这个问题但如果你是动态import或者用axios异步拉的JSON一定要注意等数据回来再注册、再渲染。4.2 主区域显示不全小心GeoJSON被二次加工有一次我用的地图包显示出来全国区域缺了很大一块检查数据里明明有对应的feature但就是不显示。最后发现是那个JSON被人做过简化处理某些几何对象格式不标准比如MultiPolygon被拆成了多个Polygon或者坐标数组的层级不对导致ECharts解析失败。这种问题没有太好的调试技巧只能逐个feature检查。我一般会写个脚本把地图里每个feature的name打印出来再跟页面显示对比找出缺的是哪一个然后单独替换那个feature的数据。如果是关键区域就放弃这个数据源换阿里云DataV的GeoJSON稳定得多。4.3 地图右下角小图总出问题中国地图的右下角都有一块小图区域表示南海诸岛。在GeoJSON数据里它通常也是一个单独的feature和主区域并列。有些精简过的地图包会把这个feature删掉或者坐标偏移导致右下角小图位置不对或者干脆没有。遇到这个问题第一步先确认数据里有没有对应名称的feature没有就换个完整的数据源。第二步如果你只需要主区域、不需要右下角小图可以在注册前把JSON里的这个feature过滤掉但要注意ECharts的map组件默认有个属性叫layoutCenter和layoutSize会影响整张图的布局过滤后需要重新调整。这块没有捷径数据源越规范问题越少。4.4 市县级地图别费劲下载用在线服务按adcode拉很多人拿到exchats-all-map之后发现里面只有省市两级没有区县数据就开始到处找XX市各区县json下载。其实没必要阿里云的DataV GeoAtlas接口可以按行政区划代码直接拉取而且是免费、支持跨域的// 以江苏省为例adcode为320000 fetch(https://geo.datav.aliyun.com/areas_v3/bound/320000_full.json) .then(res res.json()) .then(json { echarts.registerMap(jiangsu, json); // 再setOption });这个接口返回的GeoJSON包含了江苏省完整边界和市级边界。注意_full后缀代表包含下一级行政区的边界信息不带_full则只返回本级边界。做省到市下钻时记得用_full版本否则钻下去没有市级边界。4.5 3D地图不显示echarts-gl和普通地图的兼容边界凡是做过3D地图的都知道echarts-gl的map3D和geo3D跟普通地图是两套渲染逻辑。普通map系列是2D平面由canvas渲染map3D组件走的是WebGL管线对浏览器和硬件有要求。常见的问题是注册好地图配了map3D页面黑屏或者只显示一片空白。排查思路是先确认echarts-gl版本和echarts主版本兼容官方echarts-gl 2.x对应echarts 5.x版本不对会直接运行时错误再确认浏览器支持WebGL可以打开webglreport.com查一下最后检查option里map3D的map: china是否写对以及boxWidth、boxHeight、regionHeight这些三维参数是否合理。还要注意map3D和普通的series-map不支持同时渲染在同一层级。如果需要既做3D地形又叠加散点可以用geo3D scatter3D的组合坐标用经纬度数组写法和2D的scatter完全不一样这个转换是新手最容易懵的地方。4.6 低代码/框架环境地图数据加载的另类解法如果你是在低代码平台里用ECharts比如ThingsBoard或者自研的低代码搭建工具经常会遇到不能随便写import、不能往入口文件里塞自定义代码的尴尬。这时候地图数据没法用常规方式注册我的解法是把GeoJSON转成一个全局变量通过平台的自定义脚本入口塞进去再在图表配置里调用// 假设平台支持自定义脚本第一步先注册地图 window.echarts.registerMap(china, window.__CHINA_MAP_JSON__); // 第二步正常setOption如果平台连registerMap的执行时机都不可控就得做兼容处理在setOption之前轮询判断echarts.getMap(china)是否存在不存在就延迟重试。虽然丑但确实能解决低代码平台限制多、时机不可控的问题。5. 把地图从能用做到好用性能、下钻与视觉细节5.1 坐标精度裁剪压缩包能再瘦一半GeoJSON文件最大的体积来源就是坐标数据里那一长串小数点。比如经纬度106.53000000000001实际精度到4位小数已经足够前端展示。我写了一个简单的脚本在构建时对所有coordinates做精度裁剪把文件体积压掉一半以上function reduceGeoJSONPrecision(geojson, precision 4) { const factor Math.pow(10, precision); return JSON.parse(JSON.stringify(geojson, (key, value) { if (key coordinates Array.isArray(value)) { return value.map(coord { if (Array.isArray(coord)) { return coord.map(c Array.isArray(c) ? c.map(n Math.round(n * factor) / factor) : Math.round(c * factor) / factor); } return Math.round(coord * factor) / factor; }); } return value; })); }压缩之后地图视觉上几乎没有区别但网络传输和渲染性能都会明显提升。对于包含全国省级边界的数据包这个优化非常值得做。5.2 省到市下钻的完整思路地图下钻是大屏项目的标配需求。实现思路并不复杂点击省份时根据这个省的adcode去DataV GeoAtlas拉市级数据重新注册地图更新option。关键是几个细节。第一个细节是事件绑定要去重。ECharts的click事件是绑定在chart实例上的如果每次下钻都重新绑定一次点第二次时会触发多次事件。我习惯在初始化时只绑一次用chart.off(click)先解绑再绑。第二个细节是下钻层级管理。建议维护一个层级栈记录当前下钻到了哪个省、哪个市返回按钮对应出栈操作。页面里还要有个路径提示比如全国 江苏 南京让使用者知道自己在哪一层。第三个细节是下钻前后的视野切换。省级下钻后地图默认会保持全国的缩放级别不会自动缩放到该省。需要在setOption时动态设置center和zoom一般来说zoom要比全国视图大三倍左右center用该省的大致重心坐标即可。这个坐标可以从GeoJSON的所有坐标点取平均值粗略计算或者直接百度查一下省份中心点经纬度写一个映射表。5.3 让地图动起来动画和区域交互配置最后一个部分分享几个让地图更出效果的交互细节。地图初始化时可以开一个入场动画让区域从半透明到不透明、从淡色过渡到目标色。ECharts的map系列支持animationDuration和animationEasing我常用的是animationDuration: 1500, animationEasing: cubicOut视觉上比较舒服不会太浮夸。区域hover的样式也值得调。默认是加一个shadow大屏上其实可以做得更明显一点比如hover时把区域颜色提亮同时加一个外发光emphasis: { itemStyle: { areaColor: #ffd666, shadowColor: rgba(255, 215, 102, 0.8), shadowBlur: 20 } }另外如果地图上要同时展示多个维度的数据比如销售分布和渠道分布不要硬塞在一张图里。更实用的做法是加一个切换按钮动态替换series里的data和visualMap范围。这样既能保持单张图信息不过载交互上也更自然。做ECharts地图三年多我最大的感受是地图可视化真正难的不是写配置而是数据治理。一份干净的GeoJSON、一套统一的名称映射、一个可复用的注册流程比会写花哨的option值钱得多。希望这篇把这些年攒的经验都写出来能帮你少走点弯路。本文还有配套的精品资源点击获取
返回列表