概述
CRS
是 Coordinate 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]
)
关键方法解析
latlngToPoint(latlng,zoom)
作用:将地理坐标(经纬度)转换为当前缩放级别下的地图容器像素坐标
流程:
- 投影:
projection.project(latlng)
-> 平面坐标(米) - 缩放:计算当前缩放比例
scale = 256 * Math.pow(2, zoom)
- 变换:应用
transformation
调整坐标原点和缩放
pointToLatLng(point,zoom)
作用:将地图容器像素坐标转换为地理坐标(经纬度)
流程:
- 逆变换:
transformation.untransform(point, scale)
-> 平面坐标 - 投影:
projection.unproject(projectedPoint)
-> 经纬度
scale(zoom)
与zoom(scale)
作用:计算缩放级别与比例因子的转换关系
公式:
scale
:256 * Math.pow(2, zoom)
(标准瓦片尺寸为256 X 256
,每级缩放翻倍)zoom
:Math.log(scale / 256) / Math.LN2
getProjectedBounds(zoom)
作用:获取当前缩放级别下投影后的地图平面坐标范围
流程:
- 获取投影的原始边界
projection.bounds
- 应用变换矩阵得到地图容器坐标范围
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 中处理地理坐标与地图容器像素坐标转换的核心,通过整合投影和坐标变换,实现了经纬度 <–> 像素坐标的转换。