简介以中国为中心的世界地图是一份基于ECharts的网页交互式地图资源面向地理信息展示、前端可视化学习或区域数据呈现场景。它打破了传统以西方为中心的世界地图视角突出中国及周边区域位置适合需要体现多元地理视角的页面开发或教学演示。资源包共3个文件约615KB由一个可直接双击运行的HTML入口文件与两个JSON数据文件组成HTML承担地图渲染与交互JSON分别存放国家中英文名称映射数据便于二次开发和数据替换。该资源无需安装额外软件或插件打开即可使用降低了使用门槛。目前已有276人学习适合前端初学者快速上手ECharts地图应用也适合开发者直接提取JSON数据进行区域统计、地名匹配或定制化地图展示整体简洁实用。1. 以中国为中心的世界地图把地图“转个身”背后的投影与偏移逻辑做一张以中国为中心的世界地图看起来只是把默认世界地图“往左挪一挪”实际上是在重设整个投影的中央经线。很多开发者第一次接到这个需求时都以为把经纬度数据整体加个偏移就行结果出图后要么中间裂开一条缝要么地图从太平洋中间断成两半。这个需求在数据大屏、地理课件、全球业务分布展示里非常常见默认世界地图中国在最右边观众第一眼看到的却是大西洋汇报效果大打折扣。这篇笔记会讲清楚中央经线到底改了什么、一套可以直接跑通的绘图流程以及五个高频翻车点。适合需要出图交付、但又不想在地图投影上花太多时间的开发者。2. 为什么默认世界地图中国在边角中央经线决定“从哪切开”地球是个球地图是张平面把球面展开成平面必须选一条经线作为纵向中线再选一条相对经线“切开”。默认世界地图大多以本初子午线 0° 作为中央经线所以欧洲和非洲差不多在图中间中国自然就被甩到了右边缘。这个 0° 并不是什么物理铁律只是地图学早期的制图习惯。想中国居中本质就是把中央经线从 0° 改到 105°E 附近。2.1 中央经线地图的“缝合线”先理解投影里中央经线的角色。任何一种圆柱投影或伪圆柱投影墨卡托、罗宾逊、温克尔三型都会有一条经线直接落在图面的垂直中轴上这条经线的长度和方向基本不发生变形离它越远变形越大。中央经线选 0°意味着欧洲、非洲的形变最小亚洲被挤到边缘把中央经线选为 105°E中国的几何位置接近图面中心视觉上更舒服。有人会问只改中央经线全球各大洲的轮廓会不会拉伸得很奇怪 不会。中央经线改变的是“从哪里切开球面、哪条经线对准中轴”不改变投影函数本身的变形规律。换句话说中国居中的世界地图和欧洲居中的世界地图用的是同一套投影公式只是常数项不同。理解这一点后面调代码就不容易慌。2.2 直接平移经度会翻车一个常见的错误做法网上能搜到很多“让世界地图中国居中”的野路子把西半球的几何对象整体向右平移 360°。这种做法在数据上确实把美洲挪到了东边但画出来基本都会出问题。可以看下面这段代码import geopandas as gpd import shapely.affinity world gpd.read_file(data/ne_110m_admin_0_countries.shp) def shift_left_hemisphere(geom): if geom is None: return geom # 只平移西半球经度小于0的对象整体向右挪360度 if geom.bounds[0] 0: return shapely.affinity.translate(geom, xoff360) return geom world[geometry] world.geometry.apply(shift_left_hemisphere) world.plot()这段代码的逻辑是“把美洲、欧洲西段这些原本在 0° 以西的对象全部加到 360°”让全球经度统一到 0° 到 360° 的区间。但它有两个问题第一这只是让数据在数值上“搬家”投影的中央经线还是 0°中国在图上的位置仍然偏左第二0° 经线附近的国家英、法、西非一带会被拆开地图中间出现一条纵向白缝。我当时第一次做的时候也走过这条路出图之后左看右看总觉得不对劲拿中央经线一量才发现问题根本不在数据而在投影。正确做法不是手动改几何坐标而是去设置投影对象的中央经线参数。2.3 用 Cartopy 一步到位central_longitude 参数Cartopy 里做中国居中的世界地图核心只有一行参数import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature fig, ax plt.subplots( figsize(12, 6), subplot_kw{projection: ccrs.PlateCarree(central_longitude105)}, ) ax.add_feature(cfeature.LAND, facecolor#f2efe9) ax.add_feature(cfeature.OCEAN, facecolor#cfe3f7) ax.add_feature(cfeature.BORDERS, linewidth0.4) plt.show()ccrs.PlateCarree(central_longitude105)意思是使用等距圆柱投影中央经线设为 105°E。Cartopy 内部会按照这条经线重新组织坐标系绘图时自动处理跨 180° 的要素不需要手工改任何几何坐标。提醒ccrs.PlateCarree()不带参数时等价于中央经线为 0°很多老代码转过来时只改了投影类型、忘了设中央经线出来的图中国照样在右边。如果是从旧版 Basemap 迁过来的更要注意参数名差异这个后面避坑章会展开。2.4 中央经线取多少105°E 不是唯一答案中国的东西跨度大约在 73°E 到 135°E 之间简单取中点在 104°E 附近。实际制图里常用 105°E因为它是 5 的倍数刻度标注更整齐。但这不是标准答案取决于你想让中国偏左还是偏右中央经线效果适用场景90°E亚洲基本居中中国略偏右强调亚洲与中亚105°E中国接近视觉中心太平洋留白平衡大多数中国居中需求120°E中国明显偏左太平洋占大面积突出亚太与跨太平洋航线150°E中国靠左东侧留白极大特殊数据叙事少见我的习惯是先做一版 105°E再让需求方看图确认。因为“居中”是一个视觉概念数据上差几度人眼不一定看得出来但 90°E 和 120°E 的差异非常明显提前给两版对比图比事后返工高效得多。2.5 罗宾逊投影与墨卡托投影的中央经线设置差异不同投影类在 Cartopy 里的参数写法略有区别但思路相同# 罗宾逊投影中国居中 crs_robinson ccrs.Robinson(central_longitude105) # 墨卡托投影中国居中 crs_mercator ccrs.Mercator(central_longitude105) # 等差分纬线多圆锥投影中国居中国内世界地图出版物常用思路 # Cartopy 未内置该投影通常用 Robinson 或 Winkel Tripel 替代 crs_winkel ccrs.WinkelTripel(central_longitude105)Robinson 是伪圆柱投影整体形变更柔和视觉上更接近我们熟悉的“世界地图挂图”风格PlateCarree 是等距圆柱投影经纬网格是横平竖直的适合叠加散点数据和贸易航线。我个人做汇报大屏喜欢用 PlateCarree因为网格线规整、数据点好对齐做印刷级底图用 Robinson观感更专业。3. 用 Cartopy 和 GeoPandas 做一张可用的中国居中世界地图完整流程原理清楚了接下来是落地。这里给一套我经常用的流程底图数据用 Natural EarthNE公开数据集代码用 Python 的 GeoPandas 读取矢量、Cartopy 负责投影绘制。整套代码不依赖在线地图服务跑完直接存 PNG适合内网环境和自动化出图。3.1 数据准备NE 的 land、ocean、countries 三件套Natural Earth 数据集按比例尺分成 110m、50m、10m 三档。做世界底图110m 精度够用文件小、加载快。需要下载三份数据解压后放在data/目录下ne_110m_land.shp全球陆地轮廓用来填充陆地底色ne_110m_ocean.shp全球海洋面用来填充海洋底色ne_110m_admin_0_countries.shp国家边界用来描国界线NE 数据里的字段命名很稳定国家shapefile里常用的字段有ADMIN国家名、CONTINENT大洲名、NAME短名。做单纯底图不需要这些字段但如果想按大洲着色或者按国家做数值填色CONTINENT和ADMIN就是你要关联的键。3.2 核心脚本从读取数据到输出 PNGimport matplotlib.pyplot as plt import geopandas as gpd import cartopy.crs as ccrs central_lon 105 # 中央经线中国居中常用105°E # 读取NE底图数据 ocean gpd.read_file(data/ne_110m_ocean.shp) land gpd.read_file(data/ne_110m_land.shp) world gpd.read_file(data/ne_110m_admin_0_countries.shp) # 定义投影等距圆柱投影中央经线105°E crs_proj ccrs.PlateCarree(central_longitudecentral_lon) # 创建画布subplot_kw把投影挂到坐标轴上 fig, ax plt.subplots( figsize(14, 7), dpi150, subplot_kw{projection: crs_proj}, ) # add_geometries源数据是经纬度PlateCarree目标投影已由画布决定 ax.add_geometries(ocean.geometry, crsccrs.PlateCarree(), facecolor#cfe3f7, edgecolornone) ax.add_geometries(land.geometry, crsccrs.PlateCarree(), facecolor#f2efe9, edgecolornone) ax.add_geometries(world.geometry, crsccrs.PlateCarree(), facecolornone, edgecolor#555555, linewidth0.35) # 经纬网格标注放到底边和左侧避免文字压住地图中心 grid ax.gridlines(draw_labelsTrue, dmsTrue, x_inlineFalse, y_inlineFalse, linewidth0.4, color#cccccc) grid.top_labels False grid.right_labels False ax.set_title(以中国为中心的世界地图中央经线105°E, fontsize15) plt.tight_layout() plt.savefig(world_centered_105e.png, bbox_inchestight, dpi150)这段代码核心有三处理解了就能自由改。一是add_geometries的前两个参数。第一个传 GeoPandas 的geometry列第二个ccrs.PlateCarree()声明“源数据坐标系是经纬度”。这里很容易写错有人会把第二参数写成crs_proj结果就是数据被套了两层投影所有国家的轮廓都歪掉。记住一个原则源数据是什么坐标系第二参数就写什么画布坐标由subplot_kw里的投影决定。二是gridlines的x_inlineFalse, y_inlineFalse。Cartopy 默认把经纬度标注“内嵌”在网格线的终点位置也就是直接标在陆地上改成 False 后经度标注统一放底边、纬度标注统一放左侧图面干净很多。dmsTrue表示用度分秒格式显示比如105°E想要纯十进制度数改成dmsFalse。三是figsize(14, 7)。PlateCarree 投影在中央经线 105°E 时整个图面的横纵比例接近 2:114:7 正好贴合。如果改用 Robinson 投影画布比例可以保持 14:8因为 Robinson 的全球形状更接近椭圆纵向会略高一点。3.3 字体与中文标题两个配置先写上Matplotlib 默认字体不带中文直接跑上面代码标题会显示成一个个方框。中文字体配置在出图脚本里属于“先写为敬”的固定动作import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [Noto Sans CJK SC, Microsoft YaHei, SimHei] plt.rcParams[axes.unicode_minus] Falsefont.sans-serif这一行是告诉 Matplotlib 绘制文字时优先用哪个中文字体axes.unicode_minus必须设成 False否则坐标轴上的负号会显示成豆腐块。顺序上有讲究Matplotlib 会按列表顺序逐个找字体第一个找不到再找下一个。Linux 服务器上优先写 “Noto Sans CJK SC”Windows 上优先 “Microsoft YaHei”这样同一套代码在两种环境都能直接出图。3.4 参数调整从“能出图”到“能交付”底图参数没有绝对标准但有几个关键的权衡点。dpi150适合屏幕展示文件体积小做印刷或大屏投放用dpi300但渲染时间会明显变长。国界线的linewidth建议 0.3 到 0.5 之间。太粗会把陆地填色压出黑边太细打印出来看不清。海洋和陆地的颜色避免用高饱和的纯蓝和纯绿。我常用的组合是海洋#cfe3f7、陆地#f2efe9灰度印刷时也能拉开层次。如果只是描国界、不要陆地填色可以删掉land那两行把world的facecolor设成浅色填充效果更简洁。这些参数在交付时经常被反复改。我的经验是第一次出图不要追求完美先按上面默认值跑通确认投影和裁剪没问题之后再花时间调颜色和线宽。投影错了改颜色没有意义投影对了颜色随时可以迭代。3.5 中文字体在服务器上还是方框检查系统字体库rcParams只是告诉 Matplotlib “优先用某个字体”但如果系统里根本没装这个字体设置了也没用。服务器跑出方框九成是系统字体库缺失。Debian/Ubuntu 系列可以这样装apt-get update apt-get install -y fonts-noto-cjk # 安装后清理Matplotlib字体缓存 rm -rf ~/.cache/matplotlib装完字体一定要清 Matplotlib 缓存否则它还是按旧列表渲染。缓存路径在不同版本里略有差异直接删~/.cache/matplotlib是最省事的办法。Windows 和 macOS 桌面环境一般自带中文字体不需要这一步。4. 以中国为中心的世界地图避坑5 个高频翻车点的现象、原因与解决下面这五个问题都是我实际跑图过程中踩过的坑按“现象 → 原因 → 解决”写方便直接对照排查。4.1 地图中间出现一条纵向白缝现象出图后地图从中间裂开一条竖的白缝东半球和西半球像被硬生生掰开。原因典型的手动平移经度导致。把西半球几何对象整体加 360°等于把经度数值强行改到 0° 到 360° 区间但 Matplotlib 默认把经度当成普通 x 轴数值处理两个端点的数据无法在投影里“接缝”裂缝就出来了。解决不要手动改geometry的坐标改用 Cartopy 投影的central_longitude参数。Cartopy 在内部会处理经度环绕把应该相邻的区域画在一起。4.2 中央经线设置了中国仍然不在中间现象代码里明明写了central_longitude105但出来的图中国还是偏左。原因参数用错地方或者投影类型之间参数名不统一。Basemap 时代用的是lon_0Cartopy 的 PlateCarree 用的是central_longitudeRobinson 也是central_longitude。还有人把参数写进了gridlines()或者add_geometries()那只是设置了网格线的参考线根本不影响投影。解决central_longitude只写在ccrs.PlateCarree(...)、ccrs.Robinson(...)这类投影对象的构造参数里。画布拿到的是subplot_kw{projection: crs_proj}投影对象从哪里来参数就设在哪里。4.3 俄罗斯东部和南极洲出现横穿图面的长线现象地图整体正常但俄罗斯最东端和南极洲附近有一条线横穿过整个图面像地图被划了一刀。原因多边形的闭合边出了反子午线问题。一个跨过 180° 经线的国家它的轮廓点会在经度上从 179° 跳到 -179°如果绘图框架不做切割就会把这两个点用一条直线连起来正好横穿图面。解决优先使用ax.add_geometries(geom, ccrs.PlateCarree())而不是GeoDataFrame.plot(axax, transform...)前者在绘制时会按投影边界切割跨线要素。如果手头的几何对象是直接从world.geometry拿的建议先简化复杂轮廓再绘图降低切割计算量。4.4 放大地图后发现海岸线全是锯齿细节不够用现象出图缩略看没问题放大到局部就发现海岸线和国界是折线不像地图。原因用了 110m 精度的数据。110m 是“1:1.1 亿”比例尺的简化地貌全球一张图够用放大到区域级就不够看了。解决按出图比例换数据。NE 有三档110m、50m、10m。10m 数据细节最多但文件体积也最大低配机器读取会卡。我的经验是做全球大屏底图用 110m做中国周边区域图用 50m做省级或城市级边界才考虑 10m。提前问清楚最终投放的分辨率不然返工重跑很浪费时间。4.5 标题中文正常但刻度标签出现方框或乱码现象图标题中文正常经纬度刻度上的 “E”“W” 以及负数符号变成方块或者负号消失。原因刻度标签走的是另一套渲染规则默认字体里没有中文字符。axes.unicode_minus没设成 False 时负号会走特殊符号通道很容易和字体缺失问题叠在一起。解决固定开头两行rcParams配置确保系统装了中文字体。如果刻度上不想出现中文字符也可以把gridlines(dmsFalse)或改成纯数字格式减少字体负担。5. 进阶做一个“中央经线可拖拽”的交互式世界地图静态图定稿之后我一般会做一个交互版给需求方自己体验。Jupyter 环境里用ipywidgets加一个滑块就能实时拖拽中央经线直观感受中国从图右移到图中的全过程。import ipywidgets as widgets import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature out widgets.Output() def draw(central_lon): with out: out.clear_output(waitTrue) fig, ax plt.subplots( figsize(12, 6), subplot_kw{projection: ccrs.PlateCarree(central_longitudecentral_lon)}, ) ax.add_feature(cfeature.LAND, facecolor#f2efe9) ax.add_feature(cfeature.OCEAN, facecolor#cfe3f7) ax.add_feature(cfeature.BORDERS, linewidth0.4) # 在中央经线上放一个标记点用于验证中国是否居中 ax.plot([central_lon], [30], markero, colorred, markersize5, transformccrs.PlateCarree()) ax.set_title(fcentral_longitude {central_lon}°E) plt.show() widgets.interactive(draw, central_lonwidgets.IntSlider(value105, min0, max180, step5))滑块从 0 拖到 180能清楚看到中国逐渐从图右侧走向中央再偏向左。这个方法用来核对需求特别好用让需求方自己拖到他觉得“居中”的位置记下数值再按那个数出正式图省掉反复改稿。另外还有一个验证技巧值得养成习惯出图后不要只看图用代码确认地图边界。比如检查最终图的 x 轴范围是否是以 105° 为中心对称展开或者直接在图上叠加一个已知经纬度点看它是否落在预定位置。这种验证比肉眼判断可靠得多。我现在做任何地图相关需求都会先确认三件事底图数据用哪一档精度、中央经线取多少、正式发布前要不要走审图流程。这三件事确认完后面基本不会大改。做地图这件事最怕的就是数据、投影、字体各出一个小问题叠在一起就变成“玄学”。把上面的参数和坑都过一遍希望能帮你少走几步弯路。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?