《WebGIS EPSG:4326 与 EPSG:3857 墨卡托投影转换》

前言

很多 WebGIS 新手容易混淆地理坐标系 和投影坐标系:

  • EPSG:4326(WGS84):经纬度(lng/lat),球面坐标,单位:度
  • EPSG:3857(Web 墨卡托):平面笛卡尔坐标(x,y),单位:米,互联网瓦片地图标准(高德、OSM、谷歌瓦片都是 3857)

常见坑:

  1. 拿经纬度 4326 直接传给 3857 瓦片图层,地图上点位飞到很远;
  2. OpenLayers 加载 shp、GeoJSON 数据,投影不一致导致要素不显示;
  3. Mars2D、Cesium 底层是 4326,对接第三方瓦片服务返回 3857 米坐标,需要互相转换。

注意:EPSG:3857 也叫球形墨卡托,不考虑地球椭球,把地球当成正球体,是为互联网地图瓦片专门设计,不是测绘级精密投影。

一、EPSG:4326 和 EPSG:3857 基础概念对比

重点:Web 墨卡托有个明显缺陷:两极区域会无限拉伸,纬度 ±85.0511° 之外不再支持,所以 3857 有效纬度范围:-85.0511, 85.0511。

二、投影转换原理

4326 → 3857(经纬度转米坐标)

  1. 经度:线性换算,经度转 X;
  2. 纬度:正切双曲函数变换,球面墨卡托公式,纬度越高 Y 增长越快。

3857 → 4326(米坐标转回经纬度)

公式逆运算,平面米坐标还原成球面经纬度。

区别:GCJ02 是坐标偏移加密 ;4326↔3857 是投影数学变换,无加密,纯数学公式,没有迭代近似误差。

三、完整 JS 转换工具类

新建 projTransform.js,Vue、原生 JS、Mars2D、OpenLayers 通用。

javascript 复制代码
/**
 * EPSG:4326 <=> EPSG:3857 Web墨卡托转换
 * 4326: [lng, lat] 单位度
 * 3857: [x, y] 单位米
 */
const R = 6378137 // 地球半径,Web墨卡托采用

/**
 * EPSG:4326 转 EPSG:3857
 * @param {number} lng 经度
 * @param {number} lat 纬度
 * @returns [x, y] 米
 */
function wgs84To3857(lng, lat) {
  let x = lng * Math.PI / 180 * R
  let y = Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 180 / 2)) * R
  return [x, y]
}

/**
 * EPSG:3857 转 EPSG:4326
 * @param {number} x
 * @param {number} y
 * @returns [lng, lat] 度
 */
function wgs3857To4326(x, y) {
  let lng = x / R * 180 / Math.PI
  let lat = (2 * Math.atan(Math.exp(y / R)) - Math.PI / 2) * 180 / Math.PI
  return [lng, lat]
}

export default {
  wgs84To3857,
  wgs3857To4326
}

四、Vue 项目调用示例

javascript 复制代码
import proj from './projTransform.js'

// 西安坐标 EPSG:4326
const lng = 108.95
const lat = 34.27

// 4326转3857
const [x, y] = proj.wgs84To3857(lng, lat)
console.log('EPSG:3857 X,Y:', x, y)

// 3857转回4326
const [lng2, lat2] = proj.wgs3857To4326(x, y)
console.log('还原经纬度:', lng2, lat2)

五、结合 OpenLayers / Mars2D 实战场景

场景 1:OpenLayers 加载 3857 瓦片,业务数据是 4326 GeoJSON

OpenLayers 本身内置 proj4,推荐优先使用官方 proj4 库,不用手写公式,适合复杂项目:

javascript 复制代码
npm install proj4
javascript 复制代码
import proj4 from 'proj4'
// proj4内置支持4326、3857
const [x,y] = proj4('EPSG:4326','EPSG:3857', [lng, lat])

✅ 建议:少量点位转换可以手写上面公式;批量矢量数据、复杂投影,优先 proj4,减少手写 bug。

场景 2:Mars2D 中获取鼠标点击的 3857 平面坐标

Mars2D 获取屏幕点击,默认拿到经纬度 4326;如果对接第三方瓦片服务需要 X/Y 米坐标,调用上面转换函数。

六、开发高频踩坑点

  1. ❌ 混淆:GCJ02 偏移 ≠ 3857 投影
    GCJ02 是对 4326 经纬度加偏移;3857 是投影变换,二者完全独立,可以组合:WGS84 (4326) → GCJ02 → GCJ02 的 3857 投影。
  2. ❌ 纬度超过 ±85.05°,转换结果异常,Web 墨卡托不支持
  3. ❌ 单位搞错:4326 是度,3857 是米,打印日志经常看错
  4. ❌ GeoJSON 规范:GeoJSON 标准规定只能使用 EPSG:4326,如果你的 GeoJSON 是 3857,不符合规范,需要转成 4326 再存储
  5. ✅ 瓦片原理:TMS、XYZ 瓦片都是基于 EPSG:3857 切割

七、坐标系系列汇总(方便读者收藏)

  1. EPSG:4326:WGS84 球面经纬度(度)
  2. EPSG:3857:Web 墨卡托平面米坐标(互联网瓦片)
  3. GCJ02:国测局加密经纬度(高德腾讯)
  4. BD09:百度二次加密坐标系

项目组合举例:

高德底图 = GCJ02 + EPSG:3857 投影瓦片

天地图影像 = WGS84 EPSG:4326

八、总结

EPSG:4326 和 EPSG:3857 的投影转换是 WebGIS 基础底层能力。

简单一句话区分:4326 描述地球上球面位置(经纬度);3857 是把球面摊成平面,用于瓦片地图渲染 。

开发中记住:底图瓦片是什么投影,矢量数据就要对应投影,否则要素错位、不显示。

相关推荐
非科班Java出身GISer3 天前
ArcGIS JS 基础教程(48):SceneView watch 状态监听
arcgis·arcgis js基础·arcgis js入门·arcgis js监听状态·arcgis js监听事件·arcgis js 监听飞行·arcgis js 监听功能
JudithHuang5 天前
React 嵌套路由与布局
前端·react.js·arcgis·react·react router
Dxy12393102167 天前
JS DES 加密详解
开发语言·javascript·arcgis
非科班Java出身GISer9 天前
ArcGIS JS 基础教程(46):编辑要素属性 FeatureForm
arcgis·arcgis js编辑要素·arcgis js 要素·arcgis js要素属性·arcgis js 编辑属性·arcgis js编辑要素属性
梅如你10 天前
ISPRS | 1990-2020年间中国人工林与天然林的空间分布数据
arcgis·gis·遥感
limit007513 天前
公开 WMTS / XYZ 瓦片接入 Cesium:6 类常见问题与排查顺序
chrome·低代码·arcgis·web3·旅游
limit007514 天前
三维模型悬空与切片偏移的排查顺序
低代码·3d·arcgis·web3·安卓·webgl
最强小杰14 天前
Continue + minimax-m3 接入教程:协议、模型 ID、404 与工具调用排错
arcgis·ai
2501_9343044018 天前
新增2026年! 2012-2026年全国逐月夜间灯光数据
arcgis·gis数据
梅如你19 天前
中国2026年路网数据
arcgis·gis·遥感