
简介这份 ECharts 世界地图资源将中国设为地图中心面向需要在中国视角下展示全球与省市数据的前端开发者和数据分析人员可解决默认世界地图重心偏西、不便于突出中国位置的问题。压缩包共420个文件其中380个为 JSON 格式的省市边界与坐标数据40个为 JS 格式的地图配置整体约4.34MB涵盖世界地图与各省市地图脚本便于按地域灵活加载。配合 ECharts 主库使用时可快速实现以中国为中心的交互式世界地图支持地图缩放、平移、区域选中与提示窗等常见交互也能无缝下钻到中国各省市行政区域适合中国市场分析、全球业务布局、物流和贸易数据展示等场景。文件按省市拆分目录结构清晰开发者可按需引入单个或组合使用已有3153人学习下载是搭建中国视角地图应用的实用基础资源。 做数据可视化大屏的时候世界地图是个逃不开的场景。但不少人在ECharts里第一次把world.js加载出来都会愣一下地图跑出来不是以中国为中心画布正中央怼着大西洋中国缩在最右边还得手动拖回来。项目需求文档里写着“以中国为中心”你以为这只是个zoom设置问题实际处理起来却发现ECharts没有直接给你一个“中国居中”的开关。这篇就来把这件事彻底说透world.js怎么正确加载、ECharts地图的坐标体系是怎么回事、center和zoom到底怎么配才能让中国稳稳落在画布中央以及我实际项目中踩过的几个坑都一并整理出来。1. 为什么ECharts的世界地图默认不把中国放中间1.1 地图组件的显示逻辑和坐标系ECharts里的地图组件本质上是在一个平面上做经纬度坐标映射。世界地图的经纬度范围大概是经度-180到180纬度-90到90而地图数据本身只规定了每个区域的边界坐标并不会告诉你画布上应该先显示哪一块。ECharts默认的view控制逻辑是在没有显式指定center和zoom的情况下尽可能把整个GeoJSON的边界范围撑满整个画布。问题就出在这里整个世界地图的边界范围太宽了东西向跨了360度中国所在的东经73度到135度这一段在整个跨度里只占中间偏右的一小块。当整张世界地图被压缩进画布时中国自然就被挤到了右侧而地图的中心点会落在经度0度附近——也就是大西洋上空。很多人第一次看到这个结果第一反应是去翻注册代码怀疑是不是world.js的数据有问题其实数据没毛病纯粹是没有设置“观察视角”。1.2 常规操作为什么都不靠谱既然默认位置不对常见的补救办法是让用户手动拖拽或者在地图上加个按钮让用户点击后通过dispatchAction回到中国位置。这两种方案看着省事实际上在项目里都很难用。手动拖拽的问题在于每次刷新页面都要重新拖一次给客户的演示体验很差。按钮复位的方式稍微好一点但本质上是把问题后置了用户打开大屏的第一眼看到的仍然不是中国为中心。还有人会想到直接去修改world.js源码把经纬度坐标整体往左偏移这种做法伤害很大地图区域之间的相对位置会被改乱标签对不齐点位偏移得让人抓狂不到万不得已真的别碰。正确做法是用ECharts提供的center和zoom配置把地图的视角直接拉到中国区域。2. world.js从哪里拿、怎么注册才不出错2.1 不同来源的地图数据文件差异首先要明确一点ECharts从5.0版本开始官方包就不再内置地图数据了。也就是说你从npm装一个最新的echarts里面是找不到world.js的。网上搜出来的world.js大多是适配ECharts 4.x时代的老版本它内部自带了一段注册逻辑只要用script标签引入就能用。如果你项目里还是ECharts 4.x直接按老方式引入没有问题。但如果用的是ECharts 5.x就需要手动加载地图数据并调用echarts.registerMap(world, data)来注册。加载方式有两种一种是直接找JSON格式的world.json通过fetch或axios异步获取另一种是用script标签引老版本world.js。要注意的是老版本world.js在5.x下虽然能用但它的GeoJSON数据精度和边界细节相对粗糙在某些高分辨率大屏上会显得边缘锯齿明显有条件的话建议直接拿规范的GeoJSON数据。数据源方面我建议优先选择阿里云DataV的GeoAtlas它提供了按国家/地区拆分的GeoJSON数据更新及时准确性也高。其次是npm上维护的echarts-map-json这类社区包。不要随便从不知名网站下载地图文件那些数据可能是几年前从某个老项目里扒出来的少几个岛屿区域是小事国家边界画错了就是大事。2.2 registerMap注册流程的关键细节无论是JSON还是JS格式最终都要走注册这一步。JSON格式的注册代码如下import * as echarts from echarts; import worldJson from ./world.json; // 注册地图数据第一个参数是地图名称setOption时要用同一个名称 echarts.registerMap(world, worldJson);这里最容易被忽略的是注册名必须和setOption里使用的名称完全一致。我见过有人在registerMap里写的是world在setOption里写的是World或者worldMap结果地图区域一个都渲染不出来控制台也不报错排查半天才意识到是两个名称不匹配。另外如果项目里用的是script标签的引入方式会存在一个加载顺序的问题必须先加载echarts.min.js再加载world.js。因为老版本world.js内部会直接调用echarts.registerMap来完成注册如果此时echarts对象还没挂到window上就会抛出echarts is not defined。这种问题在本地开发环境可能不一定会出现一到线上部署加载慢或者缓存顺序不一致就容易翻车。稳妥的做法是使用动态import或者统一通过JSON方式加载让代码来控制注册时机。3. center和zoom的取值逻辑让中国“居中”的两种理解3.1 理解一整个世界地图完整显示中国位于视觉中心“以中国为中心”这个需求不同语境下其实是两种完全不同的效果。第一种是“整张世界地图都要露出来中国放在画布的中间视觉焦点区域”。这种效果通常用在全球业务分布大屏上需要同时看到各大洲但视觉重心要落在中国。配置方式是这样的geo: { map: world, center: [104, 35], zoom: 1.6, roam: true }center参数是一个经纬度数组[经度, 纬度]。中国的几何中心大约在东经104度、北纬35度附近大致在甘肃、陕西交界区域把这里的经纬度作为center地图就会以这个点为画布中心来展开。zoom的取值要根据你画布的实际宽高来定宽1000px出头、高700px左右的容器1.5到1.8是经验值既不会让中国显得太扁也不会把非洲和欧洲挤出画面太远。3.2 理解二加载世界地图但打开就自动聚焦中国区域第二种需求更常见虽然加载的是世界地图但页面打开后要把中国区域拉近放大看起来就像直接显示中国地图一样用户可以手动拖拽或缩放去看其他国家。这种效果适合那种“默认展示国内业务同时也想看海外分布”的场景。配置上center还是[104, 35]但zoom要拉大不少3到5都是可选的取决于你希望中国区域在画布中占据多大面积。我自己的经验是在1920x1080的大屏上zoom设4.2左右中国的轮廓正好铺满大部分画布边界留有一定余量视觉效果最舒服。如果你不确定该设多少可以先用roam开启鼠标缩放手动在页面上拖拽到满意的视角然后在监听事件里把当前center和zoom打出来填回配置里固化。这也是最直观的调试方式。3.3 容器的宽高比会影响最终显示效果还有一个很多人没注意的变量容器宽高比。同样一组center和zoom在方形容器和超宽屏上显示出来的中国位置会产生偏移。因为zoom是按比例同时缩放经纬度跨度的如果容器很宽很扁中国虽然横向居中但上下会显得空旷如果容器接近正方形中国的位置会偏上偏下更明显。这就需要一个动态适配的思路。基础的适配方式是按比例换算以基准容器宽度算出一个基础zoom然后根据实际容器宽度除以基准宽度适当调整zoom的倍数。更省事的做法是监听resize事件后重新计算zoom我用的伪代码逻辑是function calcZoom(containerWidth) { // 基准宽度1920时zoom为1.6宽度每减少一半zoom增加约0.4 return 1.6 Math.max(0, Math.log2(1920 / containerWidth) * 0.4); }这个公式不是官方算法是我自己根据多个项目效果拟合出来的经验值但能保证大多数情况下中国不会跑偏。你可以按自己项目的实际视觉效果微调系数。4. 地图数据亮起来geo与series.map两种联动方式4.1 geo组件和map系列怎么选世界地图的视觉需求很少只是孤零零画一张底图通常还要叠加数据。这时就要决定用哪一套配置体系。geo组件定位是“地理坐标系底层容器”适合用来做散点图、涟漪图、飞线图的底图。它的优势是地图和坐标系的职责分离series里放scatter、effectScatter、lines等系列时数据只要带经纬度ECharts会自动映射到geo底图上不需要额外指定坐标转换。series里直接type: map的方式则更适合做区域染色比如按国家显示业务量高低用visualMap控制颜色深浅。它的好处是数据直接通过name匹配国家名称写起来最直观但缺点是如果同时还要在地图上叠加飞线配置会变得比较复杂需要额外指定geoIndex来让飞线系列和地图共用同一个地理坐标系。实际项目里我习惯的组合是geo负责显示地图边界和视觉基底series里的effectScatter或lines系列负责业务数据的动态效果区域染色通过其他维度另外处理。这样地图作为“地理定位基础设施”的角色更清晰后续维护起来也容易扩展。4.2 涟漪散点效果怎么做才不抢戏世界地图上加业务点位最常用的就是effectScatter涟漪散点。配置上需要注意几个细节。第一个是symbolSize点位大小要根据zoom调整。世界地图缩放级别较低时一个20像素的点在中国地图上可能只覆盖一个省但放到世界地图上可能就遮住整个太平洋区域。所以不要把symbolSize写死而是根据zoom做联动zoom越大点位越大反之则缩小。第二个是涟漪效果的重绘粒度。如果数据点很多几十个以上全部开启涟漪会显得画面很乱。我的做法是让重点国家或Top级别的数据点用effectScatter次要数据点用普通scatter两层叠加既保留视觉层次又不至于糊成一团。series: [ { name: 重点标记, type: effectScatter, coordinateSystem: geo, data: [/* 带经纬度的数据 */], symbolSize: 12, rippleEffect: { brushType: stroke, scale: 3.5 } }, { name: 普通标记, type: scatter, coordinateSystem: geo, data: [/* 普通数据 */], symbolSize: 5 } ]5. 一份开箱即用的完整示例含代码5.1 完整代码示例综合前面的知识点给一份可直接复制运行的完整示例。这里使用ECharts 5.x配合JSON方式加载地图数据用geo组件配合effectScatter做涟漪散点中国作为中心出现。!DOCTYPE html html langzh-CN head meta charsetUTF-8 / titleECharts世界地图示例中国为中心/title style html, body { margin: 0; padding: 0; width: 100%; height: 100%; background: #0b1a2a; } #mapChart { width: 100%; height: 100%; } /style /head body div idmapChart/div script srchttps://cdn.jsdelivr.net/npm/echarts5.5.0/dist/echarts.min.js/script script // 说明worldJson 可以从 DataV GeoAtlas 或相关地图数据源获取 // 这里为了示例直观用 fetch 模拟异步加载 const worldJsonUrl https://cdn.jsdelivr.net/npm/echarts4.9.0/map/json/world.json; fetch(worldJsonUrl) .then(response response.json()) .then(worldJson { echarts.registerMap(world, worldJson); initChart(); }) .catch(err { console.error(地图数据加载失败, err); }); function initChart() { const chart echarts.init(document.getElementById(mapChart)); const pointData [ { name: 北京, value: [116.4, 39.9, 120] }, { name: 上海, value: [121.47, 31.23, 98] }, { name: 伦敦, value: [-0.12, 51.5, 66] }, { name: 纽约, value: [-74, 40.7, 52] }, { name: 新加坡, value: [103.8, 1.35, 45] } ]; const option { // 深色背景贴合大屏风格 tooltip: { trigger: item, formatter: function (params) { if (params.seriesType scatter) { return params.name (params.value[2] || ); } return params.name; } }, geo: { map: world, center: [104, 35], zoom: 1.8, roam: true, itemStyle: { areaColor: #1a3d5c, borderColor: #4d7eb3, borderWidth: 0.8 }, emphasis: { label: { show: false }, itemStyle: { areaColor: #2c5c8f } }, // 区域名称默认隐藏鼠标移上再显示 label: { show: false } }, series: [ { name: 重点点位, type: effectScatter, coordinateSystem: geo, data: pointData, symbolSize: 12, rippleEffect: { brushType: stroke, scale: 3.5 }, itemStyle: { color: #ffcf4d, shadowBlur: 10, shadowColor: #ffcf4d }, label: { show: true, position: right, formatter: {b}, color: #fff, fontSize: 12 } }, { name: 普通点位, type: scatter, coordinateSystem: geo, data: pointData, symbolSize: 5, itemStyle: { color: #7ee6ff } } ] }; chart.setOption(option); window.addEventListener(resize, function () { chart.resize(); }); } /script /body /html5.2 运行效果和参数微调方向跑起来之后右侧世界地图的中国区域应该正好处于画布视线焦点周围分布着几个涟漪点位。想要调整中国在画布中的占比主要改zoom想要让中国上下位置更精准微调center数组里的纬度值。我这里用的center是经验值不是通过算法精确计算的不同宽高比下你可以手动微调。另外如果地图加载出来所有区域都是同一个颜色可以先检查一下GeoJSON的每个feature里是否包含name属性。有些地图数据源给的是英文名或当地语言名和你的业务数据国家名对不上会导致区域染色或tooltip显示不正常。解决办法是在注册前对数据做一次名称映射统一替换成你系统里用的标准国家名。6. 实际项目里最容易踩的坑排名我替你先趟一遍6.1 地图加载白屏的排查顺序世界地图白屏这个问题出现频率不低。我遇到过的原因按概率排序如下第一registerMap没有在地图初始化之前完成。异步加载JSON时fetch还在返回的路上代码就已经执行到setOption此时注册表里没有world这张地图渲染结果就是空白。解决方向不是把setOption延迟而是把初始化逻辑放到fetch的then回调里像上面的示例代码一样。第二地图名称不匹配。注册名和setOption用的名称大小写或拼写不一致ECharts不会报错只会默默不画。刚才提过这里必须再强调一遍。第三DOM容器尺寸为0。很多组件是初始display:none或者父容器flex布局还没撑开此时echarts.init拿到的容器宽高都是0画出来就是空白。最常见于Tab切换页签里的图表解决办法是在容器可见之后主动调用chart.resize()。有人说地图白屏是不是echarts版本问题我实际排查下来版本导致的白屏相对少见更多还是上面三种情况。6.2 点位经纬度偏移世界地图上叠加散点经纬度数据本身错了点位就会跑到海里去。这个看似低级的问题原因是经纬度顺序搞反了。GeoJSON标准以及ECharts的value数组里统一是[x, y]也就是[经度, 纬度]。但很多业务系统里给的数据是“纬度, 经度”尤其是接手别人接口时最容易踩坑。拿到数据后先看一个国家比如北京的经纬度如果出现[39.9, 116.4]这样的顺序多半就是反了写个map函数swap一下就行。另外一个隐蔽的坑是部分散点值不是[经度, 纬度]格式而是直接传了[经度, 纬度, 数值]ECharts识别前两位做坐标定位第三位是数值这个顺序也不能乱。6.3 响应式放大缩小之后中心点偏了我做项目时遇到过这样一个问题窗口尺寸改变后调用chart.resize()地图确实跟着变了但原来居中的中国区域不再居中整体向右下角偏出了一段距离。原因是容器宽高比例改变后视口中心和经纬度中心的对应关系被重新计算了。特别是从宽屏切到窄屏中国会明显往左偏。应对方案前面提到过监听窗口变化后不仅要resize还要根据新的容器宽高重新计算center和zoom再通过chart.setOption更新。如果把地图组件封装成了Vue或者React组件记得在组件的resize回调里同时触发这两个更新不要只调用echarts自带的resize方法。说到Vue项目还有一点补充一下如果你用的是Vue2项目且集成的是limeui这样的UI组件库图表容器的高度经常会被组件自身的默认样式覆盖。建议显式给图表容器设置一个高度或者用calc()计算剩余高度避免echarts初始化时拿到高度为0的值。6.4 大屏适配时的字体和标注大小地图上的国家名称、点位label在大屏适配时也要跟着缩放。很多大屏项目用rem方案但ECharts canvas里的文字标注默认用px不会跟随html的font-size变化。我的做法是在resize回调里根据屏幕宽度换算出一个scale系数动态设置label的fontSize。具体的换算逻辑不复杂取设计稿基准宽度1920当前宽度和1920的比值就是scale系数label的fontSize乘以这个系数后重新setOption。如果只是普通后台页面而非大屏也可以不处理用户浏览器缩放或页面宽度变化时ECharts自带的resize已经能满足大部分需求。关于世界地图数据的一个补充建议不同来源的GeoJSON数据的精细程度差别很大。有的世界地图数据里外蒙古和中国的边界非常粗糙有的连一些太平洋小岛国都缺失做点位展示时就会出现数据存在但地图上找不到区域的情况。我一般是准备两套地图数据展示世界全貌用通用world.json对某个区域需要精细展示时再动态加载该区域的精细GeoJSON叠加到geo组件上。比如用户点击某个国家就让地图平滑移动到该国家并放大用registerMap注册该国精细地图后重新绘制。这种交互在ECharts里是支持动态切换的只要重新调用registerMap并setOption新的地图名称就行。最后分享一个调试技巧ECharts地图相关配置弄不清楚的时候把roam设为true自己在页面上把地图拖到想要的位置、缩放到合适的级别然后在控制台里用chart.getOption().geo[0].center和chart.getOption().geo[0].zoom打印出当前视角的准确参数拿回配置里直接固化。这套方法比对着文档猜参数值效率高得多我在好几个大屏项目里都是这么快速定下初始视角的。本文还有配套的精品资源点击获取