需求
由于项目使用矢量数据统一为大地2000坐标系(ESPG:4490),而遥感影像数据采用了多种坐标系,根据需求,需要在同一个地图控件上面显示不同坐标系的底图,每次切换底图后需要自动正确缩放到切换前地图显示范围。
坐标系 | wkid | 描述 |
---|---|---|
China Geodetic Coordinate System 2000 | 4490 | 2000国家大地坐标系 |
CGCS2000 / 3-degree Gauss-Kruger zone 37 | 4525 | 2000国家大地坐标系 高斯-克吕格投影 3度带分带 第37号分带 |
CGCS2000 / 3-degree Gauss-Kruger zone 38 | 4526 | 2000国家大地坐标系 高斯-克吕格投影 3度带分带 第38号分带 |
CGCS2000 / 3-degree Gauss-Kruger zone 39 | 4527 | 2000国家大地坐标系 高斯-克吕格投影 3度带分带 第39号分带 |
WGS 84 -- WGS84 - World Geodetic System 1984 | 4326 | 1984世界大地坐标系 |
WGS 84 / Pseudo-Mercator -- Spherical Mercator | 3857 | 1984世界大地坐标系 墨卡托投影 |
参考资料
change the crs property of map dynamically #2553 动态改变地图的CRS属性 #2553
问题
leaflet 本身不提供针对不同底图设置CRS的设置,所以切换底图后,由于切片范围计算参数没有更改,对于不同坐标系的底图没有显示到正确的位置。
解决思路
- 查看源代码,发现leaflet内置的所有矢量坐标都是转换为wgs84世界大地坐标系进行渲染显示,同时,切片计算方式则是依据map.crs对象的投影参数。矢量数据和切片数据的显示位置计算不会互相影响,所以当切片发生偏移,只需要更改map.crs对象的投影参数。
- 针对每个坐标系的投影参数创建crs对象。
- 当地图底图切换时,自动更新map.crs为对应坐标系的crs对象。
解决方案
- 使用Proj4Leaflet,创建CRS对象(leaflet自带wkid为4326和3857的CRS对象定义)
import L from 'leaflet'
import 'proj4leaflet'
const resolutions = [] // 特别重要,从地图服务定义上面获取
L.CRS.EPSG4525 = new L.Proj.CRS('EPSG:4525',
'+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=37500000 +y_0=0 +ellps=GRS80 +units=m +no_defs',
{
resolutions: resolutions,
origin:[] // 特别重要,从地图服务定义上面获取
}
);
L.CRS.EPSG4526 = new L.Proj.CRS('EPSG:4526',
'+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=38500000 +y_0=0 +ellps=GRS80 +units=m +no_defs',
{
resolutions: resolutions,
origin:[] // 特别重要,从地图服务定义上面获取
}
);
L.CRS.EPSG4527 = new L.Proj.CRS('EPSG:4527',
'+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=39500000 +y_0=0 +ellps=GRS80 +units=m +no_defs',
{
resolutions: resolutions,
origin:[] // 特别重要,从地图服务定义上面获取
}
);
- 切换图层的同时切换crs
map.on('baselayerchange', function(layer) {
let center = map.getCenter();
let zoom = map.getZoom();
map.options.crs = L.CRS.EPSG4525; // 根据图层坐标系设置
map._resetView(center, zoom, true);
})
注意
由于wgs84和大地2000坐标系定义接近,并且4490的矢量数据传入leaflet中渲染并不会产生什么偏移,所以矢量数据不需要投影。