ARTICLE DETAIL

资讯详情

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

ECharts地图实战:从GeoJSON到湖南下钻交互完整指南

ECharts地图实战:从GeoJSON到湖南下钻交互完整指南 简介针对需要在 ECharts 中展示湖南省及各市县地理分布的开发者这份地图数据包可直接用于构建省级、市级地图可视化页面。资源已对市县级地名显示坐标做了手工调整能有效避免标签重叠开箱即可配置到 ECharts 的 map 系列中配合 visualMap 实现统计数据的色阶渲染。压缩包共 22 个文件其中 15 个 json 文件包含湖南全省及长沙、株洲、湘潭、衡阳等 14 个地市的边界与区域数据4 个 js 文件为 ECharts 核心库及地图注册脚本另有 1 个 html 示例页、1 个 css 样式和 1 张预览动图整体大小仅 1.84MB轻量易用。已有 2302 人学习或下载适合前端开发者、数据分析师及相关专业学生快速接入湖南地图场景。拿到资源后既可以通过示例页面直接查看地图效果也能在自定义项目中按需引入 json 数据结合 ECharts 的 tooltip、visualMap 等组件展示人口、经济等指标省去从零整理地理边界的麻烦显著缩短开发周期。 做湖南地图这个需求我前后帮朋友折腾过好几轮从最开始一个简单的省级 GDP 展示到后来要区县下钻、移动端适配、tooltip 里塞富文本踩坑踩得相当刻骨铭心。这篇不写那种文档级别的官方教程就按照我做湖南地图时从零到一的思考路径把 echarts 地图这套东西彻底聊清楚。无论你是刚接手公司大屏项目的新人还是想给政府项目做数据可视化的前端这篇应该都能帮你少走不少弯路。1. 做湖南地图前先想清楚这三件事很多人一上来就打开 echarts 官方例子复制一个中国地图然后把 data 换成湖南省的数据结果发现地图要么是一坨空白要么干脆报错。这里面的核心问题不是 echarts 不会用而是没搞清楚地图可视化的底层逻辑。1.1 你需要的到底是“省级图”还是“市州下钻图”先别急着写代码先把需求聊透。同一个“湖南地图”在不同场景下差别非常大如果你只是需要一个静态页面展示湖南 14 个市州去年的某项指标排名这种属于省级地图只需要一份湖南全省的 GeoJSON 就能搞定但如果你做的是一块大屏用户点了长沙市想看到长沙内部各区县的数据那你要的实际上是“省级地图 市级下钻”的组合方案这就不只是准备一份数据的事了还得考虑区划层级、数据对应关系、返回逻辑、加载状态复杂度直接翻倍。从我的经验看大多数项目最终都逃不过做下钻。原因很简单领导看大屏不会只看一眼全省概况一定会点进去看某个市的数据甚至会一路下钻到区县。所以我的建议是就算第一版只做省级展示也把地图的数据结构设计成“层级分明、名字和 geoJson 一一对应”的形式不要为了图省事乱起名不然后面返工能改到你怀疑人生。1.2 ECharts 地图的原理GeoJSON 就是一切echarts 地图做出来是啥样完全取决于你丢给echarts.registerMap的 GeoJSON。官方本身不维护省市县的边界数据它只负责“画”。我给你打个比方echarts 是个打印机GeoJSON 是你塞进去的图纸图纸上有哪些边界、边界精度如何打印出来就是什么样。所以做湖南地图第一步永远是找一份靠得住的湖南省 GeoJSON。这份 JSON 文件里记录了湖南省的边界坐标、14 个市州的名称和几何范围。网上能搜到很多现成的但质量参差不齐。有些数据是十年前的边界跟现状对不上有些是简化过的放大之后边界锯齿特别明显还有一些干脆把某个市的名字写错了。我踩过最坑的一次是某份数据里“湘西土家族苗族自治州”被写成了“湘西州”而数据接口返回的 name 是“湘西土家族苗族自治州”导致这个市在 tooltip 里永远显示不出来排查了半天。这里也给一个判断数据质量的土办法拿到 GeoJSON 后先看看里面的features数量是不是 14 个再检查每个 feature 的properties.name确保这 14 个名字和你们业务数据里的市州名完全一致。不一致的要么改数据要么在代码里做一层映射千万别手写 name 去猜。1.3 数据源怎么选公开 GeoJSON 与官方地图数据很多初学者最喜欢问的一句话是你能不能直接把湖南的 GeoJSON 发我一份我的回答是这个真不能因为公开渠道的地图数据都是有版权的商用要谨慎。我自己的做法是分成两种内部项目或者 demo用开源的简易 GeoJSON 边跑通流程正式项目优先用国家地理信息公共服务平台或者各省市地理信息部门提供的数据采购或申请授权然后再转成 echarts 需要的 GeoJSON 格式。还有一种特殊情况如果只是企业内部数据看板不对外公开展示用社区里那些简化过的 GeoJSON 问题不大毕竟不涉及商业发布。但但凡涉及政府项目、对外展示的大屏老老实实走正规数据渠道别给自己埋雷。数据转换这块常用的工具是 GeoJSON 在线编辑或者 Mapshaper用来压缩简化、调整精度效果不错我每次拿到原始数据都会先用 Mapshaper 把坐标精度从 12 位压到 6 位左右体积能小掉 60%加载速度立竿见影边界肉眼看不出差别这个方法你直接用就行。2. 湖南省级地图从零跑通的最快路径思路理清之后就开始动手了。我先把最简单的省级地图跑通再往上加需求。这个“先能跑再优化”的思路做地图类需求时尤其重要。2.1 引入 ECharts 的正确姿势先说引包。echarts 支持 CDN 引入、npm 安装两种主流方式。如果是传统项目、只做这一张图直接在 HTML 里写script srchttps://cdn.jsdelivr.net/npm/echarts5/dist/echarts.min.js/script但这里有个坑要单独提一下很多人在用户现场打开页面地图死活加载不出来结果发现是现场的内网访问不了外网 CDN。我的方案是把 echarts.min.js 下载到本地放到项目的vendor目录下或者用 npm 安装之后打包进项目。npm 方式是这样npm install echarts --save然后在代码里引入import * as echarts from echarts;接下来就是注册地图和初始化容器。注意容器 div 一定要有宽高没有宽高 echarts 初始化出来就是一坨 0×0 的透明画布这个是最容易犯的低级错误但真的每天都有人踩。2.2 一个能跑的湖南全省地图配置我直接给一份能跑通的完整配置。假设我已经拿到了hunan.json这份 GeoJSON数据大概长这样一个数组每个元素是{ name: 长沙市, value: 102 }。import * as echarts from echarts; import hunanJson from ./assets/hunan.json; echarts.registerMap(hunan, hunanJson); const chartDom document.getElementById(mapContainer); const myChart echarts.init(chartDom); const cityData [ { name: 长沙市, value: 102 }, { name: 株洲市, value: 85 }, { name: 湘潭市, value: 63 }, { name: 衡阳市, value: 47 }, { name: 邵阳市, value: 38 }, { name: 岳阳市, value: 92 }, { name: 常德市, value: 74 }, { name: 张家界市, value: 22 }, { name: 益阳市, value: 55 }, { name: 郴州市, value: 49 }, { name: 永州市, value: 41 }, { name: 怀化市, value: 36 }, { name: 娄底市, value: 58 }, { name: 湘西土家族苗族自治州, value: 30 } ]; myChart.setOption({ tooltip: { trigger: item, formatter: function(params) { if (params.value undefined) { return b${params.name}/bbr/暂无数据; } return b${params.name}/bbr/指标值${params.value}; } }, visualMap: { min: 0, max: 100, left: 20, bottom: 20, calculable: true, inRange: { color: [#e8f0fe, #b3c4f0, #5b8ff9, #2b55c7] } }, series: [{ type: map, map: hunan, roam: true, label: { show: true, fontSize: 10, color: #333 }, itemStyle: { borderColor: #fff, borderWidth: 1 }, emphasis: { label: { show: true, fontWeight: bold }, itemStyle: { areaColor: #f6bd16 } }, data: cityData }] });这套配置跑起来之后你会看到一张湖南地图14 个市州按指标值从浅蓝到深蓝渐变鼠标悬停会高亮并弹出 tooltip。visualMap 会自动根据数据里的 min 和 max 计算颜色映射如果你数据里有几项特别大最好手动调一下 min 和 max不然小的那些数值颜色会糊成一片。2.3 让地图不丑颜色、悬浮与文字标签地图好不好看很大程度决定了大屏项目过不过得了验收。我在实践中总结出一个“三步美化法”第一步控制边界色。borderColor用白色或者比主色浅一号的颜色borderWidth设 1 到 1.5太粗会显得很土太细相邻区域会分不清。第二步调整 label 的显示策略。14 个市州的文字标签全部显示的话湘西那个名字特别长容易溢出边界。我一般会把字体设小一些比如 9 到 10px并且overflow: break让名字自动换行。如果你的地图是那种自定义特效的要求想让名字更从容可以开启 labelLayout 调整布局。第三步配一个合适的视觉映射方案。visualMap不只承担图例功能它的inRange.color决定了整张图的颜色情绪。政府项目偏好蓝色系企业项目可以用品牌色我个人强烈建议不要在颜色里混太多花色两个相近色阶加一个深色强调色是最稳妥的组合。还有一个小细节如果数据里某些市州没有值series 的 data 里不给这个元素就行echarts 会自动显示默认灰白色。但要注意如果你的 data 里有 name 但 value 为 nulltooltip 里会显示“null”所以要像我上面那样在 formatter 里提前判断。3. 各市地图与下钻交互一张图搞定 14 个市州省级图跑通之后最让人头疼的下钻来了。说实话下钻这个概念听起来高大上实现原理其实特别简单点某个市就重新registerMap一张这个市的 GeoJSON然后更新 series 的 map 字段。难就难在数据准备和交互状态的细节处理上。3.1 14 个市州的 GeoJSON 如何准备省级 GeoJSON 好找但 14 个市州各自的 GeoJSON尤其是精度还不错的就没那么容易了。我的经验是分两步走。第一步先用省级 GeoJSON 按需裁剪。很多社区工具支持按properties.name过滤出某个市的范围然后在 Mapshaper 里导出成独立的 GeoJSON。这样导出的市界线跟省级图完全对得上切换时不会有视觉上的跳变。第二步数据一致性。市的 GeoJSON 里的区县名称一定要和你们业务数据的区县名称对齐。这里要提醒一个常见坑长沙市有很多县级功能区域比如“湘江新区”“高新区”这些在行政区划里并不完全等同于区县如果业务数据里有这些名字而 GeoJSON 里只有“岳麓区”“望城区”就会出现点不中、显示空白的问题。我的做法是在数据层统一做名称归一业务数据里的“湘江新区”映射成“岳麓区”或者干脆在 tooltip 里单独展示字段不要动 GeoJSON 里的名字。3.2 下钻实现从省到市的两种主流方案方案一全部注册切换 map。把 14 份市州 GeoJSON 全部registerMap注册掉点击某市时 setOption 直接把 series.map 改成对应市的 key。好处是切换极快无异步加载延迟坏处是首屏资源体积大14 份 JSON 加起来可能有十几 MB。适合项目部署在本地或内网网络带宽足够的情况。方案二按需异步加载。点击时再 fetch 对应的市州 JSON注册后 setOption。这个对网络环境友好首屏只加载省级文件代价是点击后有一小段 loading。我常用的是方案二在点击事件里这样处理let isCityView false; myChart.on(click, function(params) { if (isCityView) return; fetch(./geojson/city/${params.name}.json) .then(res res.json()) .then(cityGeo { echarts.registerMap(params.name, cityGeo); myChart.setOption({ title: { text: params.name, left: 20, top: 20 }, series: [{ map: params.name }] }); isCityView true; }) .catch(() { console.warn(没有找到 ${params.name} 的地图数据); }); });关键的逻辑是isCityView这个标志位避免用户在下钻状态下再点其他市导致地图数据混乱。我见过不少新手在这里没加锁结果点长沙再点株洲地图直接飞了。3.3 从市级返回省级的交互细节下钻进去之后必须给用户一条回来的路。常规做法有两种一种是用 echarts 自带的geo组件里的按钮但那个按钮样式不可控大屏上很丑另一种是自己写一个返回按钮放在地图右上角。document.getElementById(backBtn).addEventListener(click, function() { myChart.setOption({ title: { text: 湖南省 }, series: [{ map: hunan }] }); isCityView false; });返回时还有个容易忽略的细节记得把 visualMap 的 min 和 max 还原成省级数据对应的区间不然市级的 max 和省级的 max 不一样颜色会失真。另外如果下钻后用户缩放过地图返回省级时最好myChart.dispatchAction({ type: restore })恢复默认缩放比例不然会停留在一个奇怪的视野位置。4. 移动端适配、Tooltip 显示与富文本展示地图在下钻和大屏上基本搞定之后接下来聊几个和图表相关的“周边问题”。这些热搜关键词我全都遇到或者被问过比如 echarts 折线图在移动端的适配、怎么让最后一个点的 tooltip 自动显示、以及能不能实现 echarts 展示富文本。其实这些问题里有些不是地图专属但做数据可视化项目的过程中大概率会同框出现所以一并说道说道。4.1 移动端折线图与地图的手势冲突先说一个移动端最常见的坑在手机上查看带地图或折线图的页面时页面手势和图表手势互相打架。地图上缩放是roam: true时自带的手势折线图里横向滚动是通过dataZoom实现的两个手势混在一起滑动体验非常差。我当时的解决思路是判断设备移动端把地图的roam设置成false给用户单独提供缩放按钮折线图则把dataZoom的type设为inside并且zoomOnMouseWheel设为 false避免横向滚动时误触缩放。const isMobile window.innerWidth 768; series: [{ type: map, roam: isMobile ? false : true }]另一个小技巧是给容器加touch-action: pan-y明确告诉浏览器纵向滑动交给页面横向手势交给图表实测下来流畅度提升非常明显。4.2 渲染完成后自动显示最后一个点的 Tooltip这个需求很典型图标数据看板做完折线图客户说“能不能一进来就默认显示最后一天的数据”。echarts 确实有dispatchAction可以手动触发 tooltip但很多人容易漏掉时序问题。const myChart echarts.init(dom); myChart.setOption(option); setTimeout(() { const lastIndex option.series[0].data.length - 1; myChart.dispatchAction({ type: showTip, seriesIndex: 0, dataIndex: lastIndex }); }, 300);这里的 300 毫秒是关键。echarts 在 setOption 之后需要一段时间完成渲染和布局计算如果立刻 dispatchAction可能找不到对应的图形元素。具体延时可以根据图表复杂度调整简单折线图 100 毫秒就够地图类图元多我会给到 500 毫秒。还有一种场景是页面初始化时容器还没完全展开比如 tab 切换此时需要等容器可见后再设置chart.resize()并 dispatch。4.3 在地图 Tooltip 里嵌入富文本内容关于“能实现 echarts 展示的富文本编辑器”这个关键词我的理解是你想让 tooltip 里的内容不只是纯文字而是带排版、带颜色的 HTML。这个 echarts 完全支持但有一个坑默认的 tooltip 是通过 canvas 渲染的要用 HTML 布局必须把confine或者renderMode: html打开。tooltip: { trigger: item, renderMode: html, formatter: function(params) { const data params.data || {}; return div stylemin-width:200px;padding:8px; div stylefont-size:14px;font-weight:bold;border-bottom:1px solid #eee;padding-bottom:4px; ${params.name} /div table stylewidth:100%;margin-top:6px;font-size:12px; tr td stylecolor:#999;指标A/td td styletext-align:right;color:#5b8ff9;font-weight:bold;${data.value ?? --}/td /tr tr td stylecolor:#999;指标B/td td styletext-align:right;color:#f6bd16;font-weight:bold;${data.rate ?? --}/td /tr /table /div ; } }renderMode: html会在页面上创建一个浮动的 div 来渲染 tooltip这样里面的 HTML 就能全部生效。不过要留意html 模式在大量图元时性能不如默认的 canvas 模式折线图那种上千个数据点的话不建议全局开 html可以只对图表级别的 tooltip 开。另外富文本里嵌入图片的话图片地址必须是网络可访问的不然显示不出来。如果你需要的是真正的富文本编辑器也就是在页面上编辑 tooltip 的模板那是另一套东西了可以做但思路不是改 echarts而是在编辑器里改配置项字符串然后重新 setOption。这个有点复杂一般项目用不到我建议优先用模板字符串拼接搞定。5. 常见问题排查实录这些坑我替你踩过了做图表项目遇到问题太正常了我这里把围绕 echarts 地图最常被问的几类问题做一个速查附带我自己的排查思路和解决方案。5.1 为什么 ECharts 突然访问不了了这个问题这几年出现的频率很高尤其是在传统的 HTML 单页项目里。根因基本都是引用了公共 CDN而公共 CDN 在国内的访问稳定性受各种因素影响可能时好时坏。前一段时间很多项目出现地图、图表全部打不开排查下来就是 CDN 失效。我的建议非常简单也很有效做任何项目凡是生产环境用到的 echarts一定要下载到本地或者用包管理器安装后随项目打包不要裸引用云端 CDN。如果你是因为测试临时用一下 CDN至少要加一个 failback 机制script src/vendor/echarts.min.js/script本地优先永远有一份兜底文件。此外如果你遇到的是“本地代码访问正常部署到服务器后加载不了”优先看浏览器的 Network 面板确认 echarts 文件请求是 404、403 还是超时三种情况原因完全不同。5.2 地图不显示或中间空白的排查思路地图不显示首先要做的不是改代码而是打开浏览器的 console 看有没有报错。最常见的三种第一种Invalid GeoJSON或者There is a chart instance already initialized on the dom。前者说明 GeoJSON 解析失败可能是文件路径不对或者 json 结构不对后者常见于热更新场景同一个 dom 初始化了多次解决方式是先echarts.dispose(dom)再重新 init。第二种地图画出来了但全是灰色没有你的数据。这八成是 data 里的 name 和 GeoJSON 的 properties.name 对不上我在前面 1.2 节特别强调过这里再重点说一次。排查方法很简单先不渲染任何 data直接 label 展示名字看看地图上的名字跟你的数据 name 差在哪。第三种地图的某个市显示空白其他都正常。这种情况多数是该市对应的 GeoJSON 里 feature 坐标为空或者那个市的边界数据损坏。用 Mapshaper 打开原始文件检查一遍基本就能定位。5.3 ECharts 甘特图能不能做搜到甘特图的朋友说明你的项目遇到了 echarts 常规图表解决不了的进度类展示需求。我直接说结论echarts 没有内置甘特图系列但用自定义系列或者堆叠条形图可以模拟出一个可用的甘特图只是交互会打折扣。如果你只是需要一个简单的“任务时间轴”效果用堆叠条形图是最轻量的办法x 轴用时间任务条用bar再配一个透明的背景条视觉上就是甘特图了。如果需求复杂涉及任务依赖关系、拖拽调整、进度百分比编辑那我劝你别硬和 echarts 较劲直接换一个专门的甘特图库或者自研。我用过一段时间的 dhtmlxGantt功能很全虽然学习成本高一些但能满足真实项目需求比在 echarts 里强行拼一个“假甘特”要稳妥得多。做技术选型的时候一定要记着不是所有图表都适合 echarts。写在最后一个小技巧分享地图项目做完回头看最核心的经验其实就是一句话在地图这类可视化需求里GeoJSON 数据的质量优先级高于 echarts 配置的技巧。你花一小时调试一个炫酷的配色渐变不如花一小时把数据边界、名字映射、层级关系理清楚。最后再送一个实用小技巧调试地图时如果 GeoJSON 文件里某个市画出来不对不要反复刷新页面猜直接把那一份 JSON 丢到mapshaper.org里它能可视化地展示 GeoJSON 边界还能直接编辑和导出。我每次遇到边界异常、数据合并问题都在这个工具里解决比纯靠眼睛看代码高效太多了。本文还有配套的精品资源点击获取
返回列表