源码分析之Leaflet中坐标参考系CRS对象

概述

CRSCoordinate Reference System 的缩写,即坐标参考系统

Leaflet 中CRS 是一个对象,它包含了一些方法,定义了地图坐标地理坐标之间的转换规则,如将经纬度坐标转换为像素坐标,以及将像素坐标转换为经纬度坐标,是地图渲染和交互的核心。

源码分析

源码实现

CRS的源码实现如下:

export var CRS = {
  latlngToPoint: function (latlng, zoom) {
    var projectedPoint = this.projection.project(latlng), // 经纬度 -> 平面坐标
      scale = this.scale(zoom); // 当前缩放比例

    return this.transformation._transform(projectedPoint, scale); // 应用变换
  },
  pointToLatLng: function (point, zoom) {
    var scale = this.scale(zoom),
      untransformedPoint = this.transformation.untransform(point, scale);

    return this.projection.unproject(untransformedPoint);
  },
  project: function (latlng) {
    return this.projection.project(latlng);
  },
  unproject: function (point) {
    return this.projection.unproject(point);
  },
  scale: function (zoom) {
    return 256 * Math.pow(2, zoom);
  },
  zoom: function (scale) {
    return Math.log(scale / 256) / Math.LN2;
  },
  getProjectedBounds: function (zoom) {
    if (this.infinite) {
      return null;
    }

    var b = this.projection.bounds,
      s = this.scale(zoom),
      min = this.transformation.transform(b.min, s),
      max = this.transformation.transform(b.max, s);

    return new Bounds(min, max);
  },
  infinite: false,
  wrapLatLng: function (latlng) {
    var lng = this.wrapLng
        ? Util.wrapNum(latlng.lng, this.wrapLng, true)
        : latlng.lng,
      lat = this.wrapLat
        ? Util.wrapNum(latlng.lat, this.wrapLat, true)
        : latlng.lat,
      alt = latlng.alt;

    return new LatLng(lat, lng, alt);
  },
  wrapLatLngBounds: function (bounds) {
    var center = bounds.getCenter(),
      newCenter = this.wrapLatLng(center),
      latShift = center.lat - newCenter.lat,
      lngShift = center.lng - newCenter.lng;

    if (latShift === 0 && lngShift === 0) {
      return bounds;
    }

    var sw = bounds.getSouthWest(),
      ne = bounds.getNorthEast(),
      newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift),
      newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);

    return new LatLngBounds(newSw, newNe);
  },
};

源码解析

CRS核心组成

CRS通过整合**投影(Projection)坐标变换(Transformation)**实现坐标转换:

  • projection:投影对象(如L.Projection.SphericalMercator),负责经纬度 <–> 平面坐标的转换
  • transformation:变换矩阵,处理平面坐标 <–> 地图容器像素坐标的平移和缩放
  • infinite:标识地图是否无线延申(如全球地图可横向循环)
  • wrapLng/wrapLat:经度/纬度的循环范围(如[-180, 180]
关键方法解析
  1. latlngToPoint(latlng,zoom)

作用:将地理坐标(经纬度)转换为当前缩放级别下的地图容器像素坐标
流程

  • 投影projection.project(latlng) -> 平面坐标(米)
  • 缩放:计算当前缩放比例 scale = 256 * Math.pow(2, zoom)
  • 变换:应用transformation调整坐标原点和缩放
  1. pointToLatLng(point,zoom)

作用:将地图容器像素坐标转换为地理坐标(经纬度)
流程

  • 逆变换transformation.untransform(point, scale) -> 平面坐标
  • 投影projection.unproject(projectedPoint) -> 经纬度
  1. scale(zoom)zoom(scale)

作用:计算缩放级别与比例因子的转换关系
公式

  • scale256 * Math.pow(2, zoom)(标准瓦片尺寸为256 X 256 ,每级缩放翻倍)
  • zoomMath.log(scale / 256) / Math.LN2
  1. getProjectedBounds(zoom)

作用:获取当前缩放级别下投影后的地图平面坐标范围
流程

  • 获取投影的原始边界projection.bounds
  • 应用变换矩阵得到地图容器坐标范围
  1. wrapLatLng(latlng)wrapLatLngBounds(bounds)

作用:调整经纬度到合理范围(如经度循环)
示例

  • 经度 190° -> 调整 -170°
  • 纬度 91° -> 调整 85.0511287798°(若投影支持)
坐标转换(Transformation)

作用:处理地图平面坐标到容器像素坐标的线性变换
通常用于:

  • 平移原点:如将平面坐标原点(0,0)移到地图容器中心
  • 缩放适配:根据瓦片尺寸调整比例
应用实例:CRS.EPSG38557

Leaflet 默认使用CRS.EPSG3857,即球面墨卡托投影,适合全球地图显示,其配置如下:

  • 投影L.Projection.SphericalMercator(Web Mercator)
  • 变换: 原点在左上角,缩放适配瓦片坐标
  • 循环经度wrapLng: [-180, 180]

地图坐标转换流程

  • 投影:经纬度 -> 平面坐标(米)
  • 变换矩阵:缩放 -> 像素坐标;平移 -> 容器像素坐标

总结

CRS是 Leaflet 中处理地理坐标与地图容器像素坐标转换的核心,通过整合投影和坐标变换,实现了经纬度 <–> 像素坐标的转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jinuss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值