简介:这份资源面向需要在 Web 页面中展示重庆区域地理数据的开发者,提供用 ECharts 渲染重庆地图的最小可用示例。压缩包共 2 个文件,包含 1 个 html 页面与 1 个 json 地图数据,整体约 18KB,体积轻量、便于直接嵌入现有项目。html 文件负责引入 ECharts、创建地图容器并完成实例初始化与配置,json 文件则提供重庆各区县的边界坐标,供地图系列加载绘制轮廓。借助这套文件,读者可以快速跑通地图渲染流程,理解地图类型 series 的配置方式,并在此基础上扩展区域着色、悬浮提示、点击事件、缩放平移等交互效果,用于数据分析看板、地理信息展示或区域业务监控等场景。资源已有 2425 人学习,适合具备一定 JavaScript 与 ECharts 基础的前端开发者参考,也可作为自定义重庆地图样式的起点。
1. Echarts重庆地图:为什么你的第一版总是「地图出不来」
很多前端第一次做数据可视化大屏,接到「展示重庆各区县业务分布」的需求,第一反应就是打开 ECharts 官网找地图示例,复制粘贴,然后发现——地图是空的。控制台没有报错,canvas 一片白,或者只出来一个缩在角落的方块。这不是玄学,是 ECharts 地图渲染链路里有一个环节断了。
Echarts重庆地图这件事,本质上是三件事的叠加:拿到重庆的 GeoJSON 地理边界数据、在 ECharts 里注册这份地图、把业务数据按区县名映射到地图上着色。任何一环出问题,结果都是「出不来」。它适合做区域业务监控大屏、门店分布、物流覆盖、疫情/客流热力这类按行政区划聚合的展示场景。读完这篇,你能从零跑通一张可交互的重庆地图,知道每个参数改哪里,也知道数据对不上时先查什么。
2. 地图数据从哪来:GeoJSON 的获取与注册
2.1 为什么 ECharts 5 不再内置地图数据
ECharts 在 4.x 时代内置了echarts/map/js/china.js这类文件,直接 import 就能用。从 5.0 开始,官方把地图数据从主包里剥离了,原因是地图边界涉及测绘合规,且体积大、更新频繁。所以现在你必须自己准备 GeoJSON,再通过registerMap注册。这一步是新手翻车最集中的地方——网上搜到的老教程还在写import 'echarts/map/js/chongqing.js',在 5.x 里根本找不到这个路径。
常见做法是去公开的行政区划 GeoJSON 数据源拿重庆的边界文件。重庆是直辖市,行政层级是「区/县」两级,全市共 38 个区县(26 区 + 8 县 + 4 自治县)。你拿到的 GeoJSON 里,每个 feature 的properties.name就是区县名,比如「渝中区」「万州区」「酉阳土家族苗族自治县」。这个 name 字段是后面数据映射的唯一钥匙,务必先确认它的写法。
2.2 用 registerMap 注册重庆地图的最小代码
拿到chongqing.json后,注册和渲染的最小闭环如下:
import * as echarts from 'echarts'; import chongqingJson from './geo/chongqing.json'; // 注册地图,第一个参数是地图名,后续 series.map 要用同一个名字 echarts.registerMap('chongqing', chongqingJson); const chart = echarts.init(document.getElementById('map')); const option = { geo: { map: 'chongqing', // 必须和 registerMap 的名字一致 roam: true, // 允许缩放和拖拽 label: { show: false }, // 区县名默认太密,先关掉 itemStyle: { areaColor: '#0b1a3a', // 底色,深色大屏常用 borderColor: '#2a4d8f', borderWidth: 1 }, emphasis: { itemStyle: { areaColor: '#1e5fd0' } // 悬停高亮 } }, series: [] }; chart.setOption(option);逻辑说明:registerMap把 GeoJSON 转成 ECharts 内部的地图坐标系,geo.map引用它。这里用geo组件而不是直接series-map,是因为大屏场景通常要在地图上叠加散点、飞线,geo作为独立坐标系更灵活。参数上,roam: true开启交互,但大屏如果嵌在 iframe 里,滚轮缩放会和外层滚动冲突,生产环境我一般设成'scale'或直接false,只保留拖拽。
2.3 数据映射:series-map 的 data 怎么和区县对上
地图出来了,但还是一张纯色图,因为没绑数据。绑定靠series里的map类型:
series: [{ type: 'map', map: 'chongqing', geoIndex: 0, // 复用上面 geo 的坐标系,避免重复渲染 data: [ { name: '渝中区', value: 320 }, { name: '江北区', value: 280 }, { name: '万州区', value: 150 } // ... 其余区县 ] }]关键点:data里每项的name必须和 GeoJSON 里properties.name完全一致,包括「区」「县」后缀。差一个字,这个区县就不会着色,而且不会报错——这是最隐蔽的坑。geoIndex: 0表示复用 geo 组件,如果你同时写了geo和独立的series-map且没设 geoIndex,会出现两层地图叠在一起,边界线发虚。
3. 视觉映射与交互:让数据「说话」
3.1 visualMap 分段着色的参数怎么调
纯色地图看不出数据差异,需要visualMap把数值映射成颜色。重庆各区县数据量级差异大(主城区可能上千,远郊区县几十),分段还是连续,直接影响可读性:
visualMap: { type: 'piecewise', // 分段,比 continuous 更适合区县数量多的场景 min: 0, max: 500, splitNumber: 5, pieces: [ { min: 300, label: '高 (>300)' }, { min: 150, max: 300, label: '中 (150-300)' }, { min: 50, max: 150, label: '低 (50-150)' }, { max: 50, label: '极低 (<50)' } ], inRange: { color: ['#0b1a3a', '#1e5fd0', '#4a9eff', '#a8d4ff'] }, left: 20, bottom: 20, textStyle: { color: '#cfe3ff' } }参数说明:pieces手动分段比splitNumber自动分更可控,因为业务上「主城 vs 远郊」的阈值往往是拍定的,不是等分的。inRange.color数组从低到高,深色底配浅色高值,符合大屏阅读习惯。注意max要略大于你的实际最大值,否则最高值那档颜色会溢出。
3.2 区县名标签的显示策略
38 个区县全显示标签会糊成一团,尤其是渝中、大渡口这些面积小的主城区。我的做法是分级显示:
series: [{ type: 'map', map: 'chongqing', label: { show: true, fontSize: 10, color: '#cfe3ff', formatter: (p) => p.value > 100 ? p.name : '' // 只显示高值区县名 }, emphasis: { label: { show: true, fontSize: 12, color: '#fff' } } }]formatter返回空字符串就隐藏该标签,悬停时emphasis.label强制显示。这样静态时清爽,交互时信息完整。如果一定要全显示,把fontSize降到 8 并开启labelLayout: { hideOverlap: true },让 ECharts 自动隐藏重叠标签。
3.3 点击下钻:从重庆市级到区县级的联动
大屏常见需求是点某个区县,右侧面板展示该区县明细。这靠chart.on('click')拿参数:
chart.on('click', (params) => { if (params.componentType === 'series') { const districtName = params.name; // 被点击的区县名 const value = params.value; // 触发外部面板更新,比如 Vue 里 emit 或直接操作 store updateSidePanel(districtName, value); } });params.componentType判断很重要,因为地图上可能同时有 geo、series、visualMap 等多个组件,不加判断会误触发。params.name就是区县名,直接拿去请求明细接口即可。如果要做真正的「下钻到街道」,那需要另一份街道级 GeoJSON,重新registerMap并setOption替换,注意下钻前用chart.clear()清掉旧状态,否则 visualMap 的区间会残留。
4. 避坑与排查:地图出不来时按这个顺序查
4.1 坑一:地图一片空白,控制台无报错
现象:canvas 渲染了,但没有任何图形。原因通常是 GeoJSON 格式不对——比如拿到的是 TopoJSON 而不是 GeoJSON,或者 JSON 被包了一层{ "data": {...} }。ECharts 的registerMap只认标准 GeoJSON 的FeatureCollection。解决:打开 json 文件确认顶层有"type": "FeatureCollection"和"features"数组。如果是 TopoJSON,需要先用topojson-client的feature()转换。
4.2 坑二:部分区县不着色
现象:大部分区县有颜色,个别几个始终是底色。原因几乎一定是data里的name和 GeoJSON 里的name不一致。重庆有几个名字特别容易错:「酉阳土家族苗族自治县」全称很长,有些数据源简写成「酉阳县」;「两江新区」是经济功能区不是行政区,标准 GeoJSON 里没有。解决:打印 GeoJSON 的所有 name 做对照:
chongqingJson.features.forEach(f => console.log(f.properties.name));把这份名单复制出来,和你的业务数据做一次 diff,缺哪个补哪个。
4.3 坑三:地图变形或被拉伸
现象:重庆地图看起来被压扁或拉长。原因是geo的aspectScale默认 0.75,而不同 GeoJSON 的投影方式不同。解决:设aspectScale: 1试一下,或者用layoutCenter+layoutSize手动控制:
geo: { map: 'chongqing', aspectScale: 1, layoutCenter: ['50%', '50%'], layoutSize: '90%' }layoutSize用百分比比写死像素更适应大屏分辨率变化。
4.4 坑四:resize 后地图错位
现象:浏览器窗口变化,图表跟着 resize,但地图位置偏了。原因是chart.resize()只重算容器尺寸,geo 的 layoutCenter 百分比是相对容器算的,一般没问题;但如果用了layoutSize固定像素值就会错位。解决:监听 resize 时同时chart.resize(),并把 layoutSize 改成百分比。另外大屏常用transform: scale()整体缩放,这种情况下 ECharts 的鼠标事件坐标会偏,需要额外做坐标校正,能不用 scale 就不用。
4.5 坑五:数据量太大导致渲染卡顿
现象:地图上叠加了几千个散点,拖拽缩放明显掉帧。原因是 canvas 逐帧重绘。解决:散点用large: true开启大数据模式,或者用progressive分片渲染;如果只是展示分布不要求精确位置,改用heatmap或聚合。地图本身的 GeoJSON 如果精度过高(比如包含街道级边界),也会拖慢首次渲染,市级展示用区县级精度就够,必要时用 mapshaper 简化边界点。
5. 进阶:把重庆地图做成可复用的组件
5.1 封装思路与 props 设计
一个项目里往往多个页面都要用重庆地图,重复写 registerMap 和 option 很浪费。我一般封装成一个组件,对外暴露这几个 props:
| prop | 类型 | 说明 |
|---|---|---|
| data | Array | [{name, value}]业务数据 |
| colorRange | Array | 视觉映射颜色数组 |
| onDistrictClick | Function | 区县点击回调 |
| showLabel | Boolean | 是否显示区县名 |
| roam | Boolean/String | 是否允许缩放拖拽 |
组件内部在mounted时注册地图(注册一次即可,重复注册同名会覆盖,无害但浪费),watchdata 变化时只setOption更新 series,不重建实例。
5.2 动态切换数据维度的技巧
大屏经常有「今日/本周/本月」切换,数据维度变了但地图不变。这时候不要重新 init,只更新 series 和 visualMap 的 max:
function updateData(newData, newMax) { chart.setOption({ visualMap: { max: newMax }, series: [{ data: newData }] }); }注意setOption默认是合并模式,series 数组会按索引合并,所以 series 结构要保持一致。如果切换后区县数量变了,用notMerge: true全量替换,但这样会丢失交互状态,权衡使用。
5.3 一个我踩过的教训
早期做重庆地图,我图省事把 GeoJSON 直接内联在 JS 里,文件 2MB 多,打包后首屏加载明显变慢。后来改成动态import()按需加载,地图组件进入视口才请求 json,首屏快了近一秒。另一个教训是区县名硬编码在代码里做映射,后来业务方把「某某县」改成了「某某区」,代码里没同步,地图上那个区直接消失,排查了半天。现在我的习惯是:区县名永远从 GeoJSON 里读,业务数据只负责提供 name 和 value,不做任何名称转换。地图这东西,数据源和渲染层之间多一层手写映射,就多一个翻车点。希望帮到你。
本文还有配套的精品资源,点击获取