
简介面向有一定前端基础但未接触过地图可视化的开发者和数据可视化初学者这份 ECharts 中国地图省份悬浮提示实例资源解决在网页中按省份展示业务数据、自定义悬浮提示内容并补充地图交互的常见需求。资源体积小巧压缩包仅 279KB共 4 个文件3 个脚本文件分别负责图表核心库、中国地图数据和页面辅助1 个网页文件是可直接运行的演示入口结构清晰、便于拆解学习。目前已有 575 人学习下载。示例完整演示了地图系列中省份数据的配置方式、悬浮提示框内容的自定义格式化并覆盖鼠标移入移出等事件监听以及提示信息按需加载、避免性能下降的优化思路。读者对照代码即可快速掌握从地图数据到悬浮交互的完整流程轻松迁移到实际项目中并在此基础上扩展点击省份跳转、联动其他图表等更高级的交互功能。 做地图可视化这些年说实话“中国地图带省份悬浮提示”这个需求我接过太多次了从早期的 Flash 地图到后来的 Highcharts再到现在的 ECharts几乎每一个数据大屏项目里都离不开它。ECharts 的生态成熟、社区案例多、配置灵活尤其是它自带的中国地图 geo 数据和良好的交互机制让这类需求从“能做”变成了“做得又快又好”。这篇文章我就以 echartsjs 中国地图省份悬浮提示为切入点把从零搭建一个可交互中国地图的完整思路、核心配置、常见坑点一次讲透适合刚接触 ECharts 的初学者也适合做数据可视化但一直没时间系统梳理地图组件的开发者。1. 项目整体设计与思路拆解在开始写代码之前得先把“需求”翻译成“技术方案”。省份悬浮提示这个需求看起来简单但落到 ECharts 里其实涉及几个层面的设计决策。1.1 需求拆解悬浮提示背后的三类子需求用户说“echartsjs中国地图省份悬浮提示”通常包含三层含义第一层是最基础的鼠标悬浮到某个省份上时能出现一个浮层展示该省份的名称和数据。这一层对应 ECharts 里的 tooltip 组件属于开箱即用的能力只需要配置 trigger 为 item 就能实现。第二层是视觉反馈悬浮时省份区域要高亮或者变色让用户清楚地知道当前指向的是哪个省份。这对应 series 里的 emphasis 配置可以控制悬浮时的颜色、阴影、边框等样式。第三层是数据联动悬浮提示的内容不应该只是“xx省”这么简单而是要带上具体的业务指标比如 GDP、人口、销售额、某个系统的在线用户数等。这要求地图数据源和业务数据做关联映射而且要考虑数据缺失、数值格式化等边界情况。明确了这三层方案的骨架就出来了用 ECharts 的 map 系列或 geo 组件加载中国地图数据用 tooltip 实现悬浮提示用 series.data 传入业务数据再配合视觉样式配置完成整个交互闭环。1.2 方案选型为什么用 ECharts 的 map 系列而不是 geo 组件ECharts 里画中国地图有两条路map 系列和 geo 组件。两者都能渲染地图但是定位不同。geo 组件本身是一种坐标系组件它不直接绑定数据主要作用是给 scatter、lines、effectScatter 等其他系列提供一个地理坐标系容器。如果只想要一个静态的中国地图底图用 geo 就够了但是要做省份数据的可视化比如给不同省份填充不同颜色、悬浮显示省市数据就必须使用 map 系列。map 系列是专门为地图数据可视化设计的它的 data 属性可以直接绑定省份维度并且自动和 tooltip 联动。在同一个图表实例中map 系列也可以和 geo 同时使用比如用 geo 画底图用 map 系列叠加数据层但这属于进阶玩法大部分场景下单独用 map 系列即可。还有一点要注意的是ECharts 5 和 ECharts 4 在 map 系列的使用上有个重要差异ECharts 4 中地图数据默认自适应 viewport不需要额外配置ECharts 5 中则需要显式设置map: china并且在注册地图数据后配合roam、center、zoom等参数来调整视野。这个差异是很多从旧项目迁移到新版本后地图死活显示不出来的主要原因之一下文会专门讲。1.3 地图数据获取一个必须解决的隐藏问题ECharts 从 4.9 版本开始不再内置中国地图的 GeoJSON 数据。也就是说你就算引入了 echarts.min.js直接写map: china也渲染不出来控制台会报错 “GeoJSON named china has not been loaded”。这个问题的解决方案主要有三种一是从 ECharts 官方 GitHub 仓库下载历史版本中自带的china.js文件引入后会自动注册地图。文件里的数据格式是 GeoJSON 编码后的字符串体积大概一百多 KB对于本地项目来说很友好。二是从第三方开源 GeoJSON 数据源获取比如 DataV.GeoAtlas 、阿里云数据可视化平台等地方下载中国省级行政区划的 GeoJSON 文件用echarts.registerMap(china, geoJson)手动注册。三是直接使用 ECharts 官方提供的在线 map 数据地址如果项目允许加载外网资源运行时动态加载。我个人在实际项目中的建议是如果是内网部署或对加载性能有要求把 GeoJSON 文件下载到本地通过registerMap注册如果是内部工具类项目允许访问外网可以直接在官方 CDN 上引一个china.js省事。后面实操部分我会贴出完整的代码。2. 核心细节解析与实操要点这一部分主要讲悬浮提示相关的三块核心配置tooltip 的细节、map 系列的联动关系、以及数据格式的匹配规则。很多人地图画出来了悬浮提示也能弹出来但总觉得界面粗糙、交互不自然问题基本都出在这三块没吃透。2.1 tooltip 配置悬浮框的高级玩法默认情况下map 系列的 tooltip 只要设置了trigger: item悬浮到省份上就会显示该省的名称和数值。但默认样式的可定制性比较差在真实项目中通常要覆盖几个关键字段tooltip: { trigger: item, backgroundColor: rgba(20, 40, 80, 0.9), borderColor: #409eff, borderWidth: 1, padding: [12, 16], textStyle: { color: #fff, fontSize: 14 }, formatter: function(params) { if (params.data) { return div stylefont-weight:bold;margin-bottom:6px; params.name /div div数值 params.data.value /div div占比 (params.data.percentage || -) /div; } return params.name; } }这里需要注意的一点是params.data在初次渲染时可能是 undefined。因为地图的 tooltip 默认依赖 series.data 里的数据项如果某个省份没有对应数据data 就是空的所以 formatter 里一定要做判空保护否则悬浮到无数据的省份上控制台就会报错。另外params.data里除了 value所有你自己塞进去的字段都能取到比如上面代码里的percentage。这就意味着你可以在数据源里放任意自定义字段比如 GDP、增长速率、排名、目标值等在 formatter 里组合出一个信息量很大的提示框。这是悬浮提示的核心价值所在——它不是一个简单的数值气泡而是一个信息聚合容器。对于追求视觉效果的大屏项目还可以利用 formatter 返回 HTML 字符串的特性在悬浮框内嵌一个简单的柱条、圆点、进度条等类似这种信息密度高的浮层往往比图表主体更能打动客户。2.2 map 系列的抖动问题与 emphasis 视觉反馈地图悬浮的视觉反馈主要体现在 emphasis 配置上。很多初学时把 emphasis 写成了emphasis: { itemStyle: { color: ... } }但没效果大概率是因为把 series 里的 emphasis 写错层级或者和 select 混在一起。map 系列的强调状态结构应该是series: [{ type: map, map: china, emphasis: { itemStyle: { areaColor: #ffd666, shadowColor: rgba(255, 180, 80, 0.8), shadowBlur: 18 }, label: { show: true, color: #333 } } }]shadowBlur配合shadowColor可以做出悬浮时省份发光的质感这是大屏里非常常用的技巧。另外还可以通过emphasis.disabled: true关闭悬浮高亮效果适用于某些只需要点击交互的场景。还有一点容易被忽略地图边界线的粗细颜色在 itemStyle 的borderColor和borderWidth中配置而悬浮时高亮区域的描边在 emphasis.itemStyle 里同样有一份borderColor。如果两份配置不统一会出现“悬浮时边界线风格突变”的问题影响整体观感。2.3 数据匹配规则省份名称必须严格一致ECharts 地图数据联动的机制是根据name字段匹配的。也就是说series.data 里的每一项的 name 必须和 GeoJSON 属性中的 name 完全一致才能真正把数据挂到对应的省份上。这里有几个非常隐蔽的坑“北京”和“北京市”不完全等价。虽然 ECharts 内部对部分省市做了别名兼容但这种兼容并不可靠建议统一用全称比如“北京市”“河北省”。“内蒙古”和“内蒙古自治区”很容易混用。GeoJSON 里注册的官方名称是“内蒙古自治区”如果用简称“内蒙古”数据会挂不上去悬浮提示显示不出来。“广西壮族自治区”“宁夏回族自治区”“新疆维吾尔自治区”这类名称比较长做数据源的时候经常被简化也容易造成不匹配。香港、澳门、台湾在官方 GeoJSON 里的名称是“香港特别行政区”“澳门特别行政区”“台湾省”数据处理时要特别留意。最稳妥的办法是自己写一个名称归一化函数把简称转换成官方全称。下面是实际用过的一套映射逻辑const nameMap { 北京: 北京市, 上海: 上海市, 天津: 天津市, 重庆: 重庆市, 内蒙: 内蒙古自治区, 广西: 广西壮族自治区, 宁夏: 宁夏回族自治区, 新疆: 新疆维吾尔自治区, 西藏: 西藏自治区, 香港: 香港特别行政区, 澳门: 澳门特别行政区, 台湾: 台湾省 }; function normalizeName(name) { return nameMap[name] || name; }这个函数配合数据预处理流程放在图表渲染之前执行简单有效能直接消灭掉大部分“数据传了但不显示”的问题。3. 实操过程与完整代码实现下面这套代码是我在实际项目里抽出来的一个可直接运行的版本画一个标准中国地图带各省份悬浮提示能够自适应容器大小并且支持缩放拖拽。完整复制到一个 HTML 文件里就能看到效果。3.1 准备文件与引入顺序先准备好三个文件echarts.min.js本地或 CDN 均可、china.js含 GeoJSON 地图数据、自建的 index.html 和 data.js业务数据。引入顺序很关键一定要先引 echarts再引 china.js最后是业务数据因为 china.js 内部会调用 echarts.registerMap如果 echarts 还没加载完会报 “registerMap is not a function”。!DOCTYPE html html langzh-CN head meta charsetUTF-8 / titleechartsjs中国地图省份悬浮提示/title style html, body, #map { width: 100%; height: 100%; margin: 0; background: #0b1e3f; } /style /head body div idmap/div script srchttps://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js/script script srchttps://cdn.jsdelivr.net/npm/echarts4.9.0/map/js/china.js/script script srcdata.js/script script srcmain.js/script /body /html注意上面我用了echarts4.9.0的 china.js这是官方仓库里最后一份内置中国地图数据的版本和 ECharts 5 完全兼容可以直接通过 registerMap 注册。如果想离线部署就把这两个 js 文件下载到本地。3.2 数据源格式与省份过滤data.js 里的数据我是模拟了一批各省级行政区 2024 年的“项目验收数”和“通过率”以便演示悬浮提示的完整字段结构var regionData [ { name: 北京市, value: 128, passRate: 96.3% }, { name: 上海市, value: 102, passRate: 94.5% }, { name: 广东省, value: 231, passRate: 92.8% }, { name: 江苏省, value: 187, passRate: 93.1% }, { name: 浙江省, value: 154, passRate: 95.2% }, { name: 四川省, value: 76, passRate: 89.7% }, { name: 湖北省, value: 63, passRate: 91.4% }, { name: 陕西省, value: 91, passRate: 88.9% }, { name: 黑龙江省, value: 45, passRate: 90.2% }, { name: 其他, value: 0, passRate: - } ];这里有个小技巧凡是拿不到数据的省份就不要写进数组里。ECharts 会自动给没有数据的省份一个默认色。不要人为地把缺失数据统统塞成 value: 0因为 0 值在地图配色里也是有视觉含义的会让用户误以为“该省份数值为 0”而不是“没数据”。3.3 ECharts 初始化和核心图表配置main.js 里的内容就是核心了。我直接给出完整配置并在关键行加上详细注释var chart echarts.init(document.getElementById(map)); var option { tooltip: { trigger: item, backgroundColor: rgba(20, 40, 80, 0.9), borderColor: #409eff, borderWidth: 1, padding: [12, 16], textStyle: { color: #fff, fontSize: 14 }, formatter: function(params) { if (!params.data) { return params.name; } var info params.data; return div stylefont-weight:bold;margin-bottom:6px; info.name /div div验收项目数b info.value /b 个/div div通过率 (info.passRate || -) /div; } }, visualMap: { min: 0, max: 240, left: 20, bottom: 20, text: [高, 低], calculable: true, inRange: { color: [#1e4b8f, #2f7ed8, #4ea3f2, #7ec7ff, #c8e9ff] }, textStyle: { color: #fff } }, series: [{ name: 项目验收数, type: map, map: china, roam: true, emphasis: { itemStyle: { areaColor: #ffd666, shadowColor: rgba(255, 180, 80, 0.8), shadowBlur: 18 }, label: { show: true, color: #333 } }, itemStyle: { areaColor: #2b5c9e, borderColor: #8ecbff, borderWidth: 1 }, label: { show: true, color: #fff, fontSize: 10 }, data: regionData, nameMap: { 北京: 北京市 } }] }; chart.setOption(option); window.addEventListener(resize, function() { chart.resize(); });这里需要特别说明三点第一roam: true是开启地图交互的关键参数允许鼠标拖拽和滚轮缩放。如果不设置地图固定视角悬浮功能不受影响但大屏演示时用户无法聚焦感兴趣的省份实际使用体验会比较受限。第二formatter 里的b标签和margin-bottom内联样式可以正常生效因为 ECharts 的 tooltip 内容支持 HTML 字符串允许这样进行局部样式定制。第三visualMap 中inRange.color定义了从低到高的颜色渐变序列它是根据省份 value 值自动着色的和悬浮高亮的 emphasis.itemStyle.areaColor 互不冲突。一个是常态下的数据映射一个是悬浮时的瞬时反馈。3.4 异步加载数据和动态更新真实项目中数据往往不是写死的而是从接口动态拉取。一个常见的做法是初始化一个空地图请求数据后通过setOption更新 series.datafetch(/api/region/stats) .then(function(res) { return res.json(); }) .then(function(data) { chart.setOption({ series: [{ data: data }] }); });这种方式只更新 data不会重置 tooltip、visualMap 等其他配置也不会让地图闪烁。性能上没什么问题因为 setOption 内部是 diff 合并不是全量替换。有一点值得提醒如果接口里的省份名称是简称需要先经过归一化处理再塞给 data。不要试图在数据里偷懒用别名ECharts 的匹配机制决定了你必须保证 name 精确匹配才能正确联动悬浮提示。4. 常见问题与排查技巧实录做 echarts 中国地图悬浮提示时我踩过的坑、帮别人排查过的问题来来去去主要集中在那么十几个点上。这里挑高频的记录下来每条都配有定位和解决方法希望能帮你省去一些排查时间。4.1 地图白屏不显示的排查矩阵白屏是遇到最多的问题原因五花八门但定位路径是固定的。我整理了一个排查顺序表序号检查项检查方法解决方案1是否注册了地图数据控制台是否有 “GeoJSON named china has not been loaded”引入 china.js 或手动 registerMap2容器是否有高度检查 #map 的 height 是否为 0给容器设置固定高度或 100%3DOM 是否已就绪init 是否在 DOM 加载前执行把初始化代码放到 window.onload 或 body 底部4ECharts 版本与地图数据是否兼容控制台是否有其他报错统一使用 ECharts 5.x china.js 4.9.05是否同时存在多个 echarts 实例检查是否重复初始化使用前调用 chart.dispose() 释放旧实例其中第 2 条是隐藏最深的坑很多框架里初始化图表时容器还没布局完成高度算出来是 0地图就渲染成空白。遇到这种情况可以在 init 前打印一下document.getElementById(map).clientHeight如果输出 0基本就是这个原因。4.2 悬浮提示不出现的三种典型场景第一种场景tooltip 配置了 trigger: item但悬浮就是没反应。排查思路是先看 series 里有没有配置data如果没有给 map 系列传 datatooltip 的显示会异常。此时可以先不依赖业务数据给 series.data 随便加一条测试数据验证。第二种场景悬浮到某些省份有提示某些省份没提示。这种情况几乎都是数据名称不匹配。解决方案就是把数据名字和 GeoJSON 里的属性名逐一比对字符级差异都不能放过。第三种场景提示框能出来但内容是 undefined。这通常是 formatter 里引用了params.data.value而某个省份确实没有数据。formatter 里必须做判空保护至少 return 一个省份名称。4.3 数据动态更新后视觉映射不生效怎么办动态更新后有一种情况是地图形态更新了但颜色还是老样子。这通常是因为 visualMap 的 min/max 范围没跟着新数据调整。比如老数据最大是 100新数据最大是 1000visualMap.max 还停在 100那么所有超过 100 的省份都会被渲染成最深色看起来像“没更新”。处理方案是每次接口返回数据后动态计算 min/max 再 setOptionvar values data.map(function(item) { return item.value; }); chart.setOption({ visualMap: { min: Math.min.apply(null, values), max: Math.max.apply(null, values) }, series: [{ data: data }] });如果你希望颜色区间稳定不随数据变化而变那就把 visualMap 的 min/max 固定成一个业务上的合理区间比如全国统一为 0-1000这样不同月份的数据对比起来才有意义。4.4 大屏适配与性能优化心得做数据大屏的时候地图往往是整个页面的视觉中心性能和适配问题一定要提前考虑。分辨率适配方面最稳妥的做法是不依赖 ECharts 的默认自适应而是在容器尺寸变化时主动调用chart.resize()并且考虑用 ResizeObserver 监听容器而不是只监听 window resizevar observer new ResizeObserver(function() { chart.resize(); }); observer.observe(document.getElementById(map));性能方面如果地图里还要叠加散点、飞线大量的动画和元素同时渲染帧率会明显下降。这个时候优先考虑关闭不必要的动画animation: false并且合理设置large: true来开启大数据量优化模式。对于纯地图 悬浮提示这种轻量交互ECharts 的渲染性能是绰绰有余的不用过度优化。5. 进阶扩展从 2D 地图到 3D 效果和新版 ECharts 的兼容处理项目做完基础功能后总会有人问能不能加一些更炫的效果。这里把常见的两类进阶需求和对应的处理思路一并梳理清楚。5.1 ECharts 6 与 echarts-gl 中实现 3D 中国地图的要点如果需要在 3D 场景里展示中国地图最常见的方案是 echarts-gl 插件。echarts-gl 里提供了一个map3D系列和普通的 map 系列配置非常接近。注意要使用支持 map3D 的 echarts-gl 版本并指定map: china数据通过 series.data 传入。实现 3D 地图的时候要注意map3D 的悬浮提示同样走 tooltip但触发时默认弹出浮层的位置和 2D 略有不同3D 场景下提示浮层通常会固定在一个位置不会跟随模型表面移动这是正常行为不是 bug。如果要控制地图的倾斜视角和旋转需要在 map3D 配置里设置viewControl比如alpha控制俯仰角、beta控制水平旋转角、distance控制观察距离。不要用roam来控制 3D 地图的交互map3D 里没有这个属性3D 交互统一由 viewControl 负责。5.2 多地图联动、自定义数据叠层和钻取下钻悬浮提示只是交互的第一步很多项目后续会要求点击某个省份下钻到该省的市级地图。这种场景下有一个关键点初始化时需要同时注册全国地图数据和各省级地图数据点击时切换 series 的 map 属性并渲染新的数据。切换地图时为了避免视觉闪烁建议把 data 和 map 绑定在同一个 setOption 中更新并且关闭过渡动画。另外如果要在同一张地图上叠加多组数据比如同时展示“项目数”和“通过率”ECharts 5 支持在同一 series 数组里配置多个 map 系列。但两个 map 系列会相互覆盖需要合理设置透明度和 zlevel通常做法是一个系列画底色另一个系列只画部分区域或者用 label 展示数据。这里比较容易出问题的是两个系列的悬浮提示会互相干扰所以实际项目中我通常会把非主系列设置tooltip: { show: false }避免出现双层提示框的尴尬。6. 踩坑记录与个人经验补充最后再聊几点代码之外的经验这几条在官方文档里是看不到的但实际项目里我几乎每次都用到。第一关于地图数据源。如果你所在的项目对数据安全有要求不能加载外网 CDN那 china.js 一定要提前下载到本地并且做好资源版本管理。ECharts 版本升级时china.js 不需要跟着升级因为 GeoJSON 数据是独立的只要 registerMap 正常地图就能渲染。第二关于悬浮提示的样式。tooltip 里的 formatter 返回 HTML 时外部容器默认会有一些 ECharts 自带的 padding 和背景色如果不想要可以在 formatter 返回的字符串里再包一层 div完全接管样式。这样能做到和大屏主题完全一致的自定义效果。第三关于数据异常处理。接口返回的数据里如果某个省份的 value 是 null 或负数务必在进入图表前做数据清洗否则 visualMap 的颜色映射会错乱map 系列对负数的处理时好时坏有的版本会直接渲染成最浅色有的版本会报错。统一在数据源层面兜底是最省心的。第四关于悬浮提示在触屏设备上的体验。默认的 hover 事件在平板上没有对应动作需要设置tooltip.triggerOn: click来让点击也能弹出提示框。如果想同时兼容鼠标和触屏可以在 tooltip 里配置triggerOn: mousemove|click这一点在演示现场很容易被忽略。按照这套流程把 echartsjs 中国地图的省份悬浮提示做出来整个地图可视化的基础交互就打通了。剩下的无非是在这个骨架上填充不同业务数据、调整配色风格、叠加其他图表模块本质上都是围绕这个核心交互做文章。希望这篇内容对你有用有任何配置细节上的问题也欢迎在评论区继续交流。本文还有配套的精品资源点击获取