购买课程
QGIS 与 EPSG:3857 投影:底图哪里来

QGIS 与 EPSG:3857 投影:底图哪里来

免费试读 · 约 24 分钟阅读

从 QGIS 安装到出第一张地形栅格,所有命令都给你写好。

很多前端开发者第一次碰地图项目,会下意识把地图当成「一张图片」。这在静态展示里没问题,但只要你要做点位、镜头、区域切换、地形起伏、水体遮罩,就不能再这么理解了。地图在工程里不是图片,而是一套坐标系统下的资产集合。

这一节要解决一个核心问题:浏览器里的古风地图,究竟是怎么从真实地理世界变成 Three.js 场景的?你不需要成为 GIS 专家,但 CRS、投影、bounds、栅格、遮罩这几个概念必须搞清楚。否则你后面遇到的所有错位、拉伸、点位漂移,本质上都不知道从哪里排查。

要不要学 GIS 底层算法

先给结论:不需要系统学完整 GIS,但必须理解前端可视化绕不过去的那部分。就像做 Agent 不一定要训练大模型,但你要知道 token、KV Cache、上下文窗口为什么影响工程;做地图可视化也不一定要研究地理测绘,但你要知道投影、坐标和栅格为什么会影响画面。

如果你只会导出一张 PNG,你能做出第一版;如果你理解这张 PNG 背后的 bounds、分辨率、投影和像素坐标关系,你才能做出第二个区域、第三个区域,并且让诗词点位稳定落在正确位置。

真实世界坐标为什么不能直接进 Three.js

真实地理位置通常用经纬度表达,比如某个地点是东经 104.06、北纬 30.67。这个坐标描述的是地球表面的位置,而 Three.js 场景里的坐标是一个三维笛卡尔空间。两者不是一个世界。你不能简单把经度当 x、纬度当 z,然后期待地图看起来正确。

  • 经纬度单位是角度,不是米,也不是像素。
  • 同样 1 度经度在不同纬度对应的真实距离不同。
  • 地球是曲面,屏幕和 Three.js 地形平面是平面。
  • 地图图片有自己的裁切范围和像素尺寸,点位必须落到同一套范围内。

所以中间必须有一个转换过程:先把地球表面的经纬度投影到平面坐标,再把平面坐标归一化到地图图片的像素范围,最后再映射到 Three.js 的世界坐标。QGIS 和 GDAL 就是在帮我们把前两步做稳定。

为什么统一用 EPSG:3857

EPSG:3857 是 Web 地图最常见的墨卡托投影。你在很多在线地图、瓦片服务、Web 地图 SDK 里看到的底图,基本都围绕它工作。它不是最适合所有地理分析的投影,但对前端工程来说,它最大的优点是生态统一、资料多、工具链顺。

投影的本质,是把地球曲面上的点摊到平面上。摊开的方式不同,就会造成不同的面积、距离、形状变形。诗贯山河不是做严肃测绘,不需要每一公里都绝对精确;它更需要的是:不同图层能对齐,点位能稳定映射,资产能重复导出。EPSG:3857 正好满足这个目标。

  • 统一投影后,区域边界、诗词点位和高程栅格可以在同一坐标系里对齐。
  • 前端只需要做归一化映射,不需要运行复杂地理投影库。
  • 后续新增四川、陕西、洛阳时,可以复用同一套导出 SOP。

bounds 是地图项目的生命线

如果只记一个概念,请记 bounds。bounds 描述的是这张地图图片覆盖的真实投影坐标范围:最小 x、最小 y、最大 x、最大 y。它相当于告诉前端:这张 2048×2048 的纹理,对应真实世界平面坐标里的哪一块区域。

没有 bounds,你只能靠眼睛摆点位。今天看起来对了,换一张分辨率、换一次裁切、换一个区域,点位就会全部漂。保留 bounds 后,任何经纬度点都可以按同一套公式映射到纹理坐标,再映射到 Three.js 世界坐标。

  1. 经纬度先投影到 EPSG:3857 平面坐标。
  2. 用 bounds 计算它在区域内的相对比例 u、v。
  3. 用 u、v 映射到纹理像素或 Three.js 平面坐标。
  4. 相机、点位、特效 Volume 都使用这套统一坐标结果。

一套区域资产应该包含什么

  1. 区域边界:决定画面裁切范围,也决定后续纹理的有效区域。
  2. 地形高程:给 Three.js 地形 shader 使用,通常会编码到 RG 通道。
  3. 河流 / 水体遮罩:给水面材质和水墨边缘使用,避免整张图都泛水光。
  4. 视觉底色:给用户第一眼的风格定调,可以是水墨、宣纸、地形阴影或混合结果。
  5. 坐标映射参数:记录 bounds、宽高、中心点和缩放比例,供前端把经纬度转成屏幕位置。

为什么不在前端实时处理 GIS

理论上,前端可以引入投影库、读取 GeoJSON、实时栅格化边界、动态生成遮罩。但诗贯山河不这么做。原因很现实:运行时越复杂,加载越慢,移动端越不稳,调试也越困难。前端最擅长的是渲染和交互,不应该承担重型资产生产。

更合理的分工是:QGIS / GDAL 在离线阶段把复杂地理数据处理成稳定资产,前端只消费纹理和配置。也就是说,我们把不确定性尽量前移到资产生产阶段,而不是留到用户打开页面时。

导出时最容易错的点

  • 没有统一 CRS,导致边界、河流、点位看起来都差一点点。
  • 导出分辨率随手填,前端纹理尺寸过大或过小。
  • 裁切范围每次手动拖,导致同一区域多张图无法像素级对齐。
  • 忘记记录 bounds,后续坐标映射只能靠猜。

一个最小可复用 SOP

  1. 确定区域:先明确要做全国、省份、城市还是局部文化区域。
  2. 统一投影:所有图层转到 EPSG:3857,不要混 CRS。
  3. 固定裁切:用明确 bounds 裁切,而不是手动拖出一个差不多的范围。
  4. 统一尺寸:底图、高程、遮罩保持同样分辨率,避免像素不对齐。
  5. 导出配置:把 bounds、width、height、center、scale 写进区域配置文件。
  6. 前端验收:用几个已知城市点位检查是否落在正确位置。

怎么判断你的地图资产是健康的

  • 同一区域的底图、高程图、水体遮罩尺寸完全一致。
  • 所有资产来自同一个 CRS 和同一个裁切 bounds。
  • 前端不需要手动给每个点位加奇怪偏移才能对齐。
  • 换分辨率时,只要 bounds 不变,点位位置仍然稳定。
  • 新增区域时,你能按 checklist 复现,而不是靠记忆操作。

本节总结

QGIS 不是这门课的主角,但它决定了诗贯山河的下限。如果地图资产不可靠,后面的 Three.js、shader、特效、镜头都会建立在漂移的地基上。反过来,只要投影、bounds、分辨率、资产命名这几件事守住,前端就会轻很多。

从这一节开始,你要把地图理解成「带坐标契约的资产包」,而不是一张好看的背景图。这个认知会贯穿后面所有地形、点位和镜头章节。