leaflet加载不同投影的图层

需求

由于项目使用矢量数据统一为大地2000坐标系(ESPG:4490),而遥感影像数据则是使用6度带分带的平面坐标系,导致了geosjon格式的矢量数据和切片格式的影像数据使用了不同的坐标系。

在项目的前端使用了leaflet框架作为地图渲染框架,由于leaflet默认没有提供加载投影图层的接口,所以需要自行制作解决方案。

参考资料

change the crs property of map dynamically #2553 动态改变地图的CRS属性 #2553

方法

  1. 切换图层的同时切换crs
map.on('baselayerchange', function(layer) {
        let center = map.getCenter();
        let zoom = map.getZoom();
        console.log(map.options.crs)
        if (layer.name.indexOf('百度') > -1) {
            map.options.crs = L.CRS.Baidu;
            map.options.tms = true;
            map._resetView(center, zoom, true);
        } else {
            map.options.crs = L.CRS.EPSG3857;
            map.options.tms = false;
            map._resetView(center, zoom, true);
        }
})
复制代码
  1. 切换crs的时候要对map进行操作刷新地图中心点
map.removeLayer(map.curLayer);
var center = map.getCenter();
map.options.crs = map.newLayer.crs;
map.setView(center); //we need this, because after changing crs the center is shifted (as mentioned above probably it's an issue to)
map._resetView(map.getCenter(), map.getZoom(), true); //we need this to redraw all layers (polygons, markers...) in the new projection.
map.addLayer(map.newLayer);
复制代码
  1. 切换crs之后,要对geojson数据进行重新投影

(1) 定义所需坐标系

//China Geodetic Coordinate System 2000(cgcs2000)
//国家2000地理坐标系
proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");

//CGCS2000 / 3-degree Gauss-Kruger zone 37
//37度带
proj4.defs("EPSG:4525", "+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=37500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");

//CGCS2000 / 3-degree Gauss-Kruger zone 38
//38度带
proj4.defs("EPSG:4526", "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=38500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");

//CGCS2000 / 3-degree Gauss-Kruger zone 39
//39度带
proj4.defs("EPSG:4527", "+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=39500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");

复制代码

(2) 坐标转换

//将坐标点从大地坐标系转为平面坐标系37、38、39带
tranformCoordsToPlane: function (lng, lat, fromEPSG) {
fromEPSG = fromEPSG || 'EPSG:4490';

var EPSG;

if (lng < 112.5) {
  EPSG = 'EPSG:4525';
} else if (lng > 112.5 && lng < 115.5) {
  EPSG = 'EPSG:4526';
} else {
  EPSG = 'EPSG:4527';
}

var coord = proj4(fromEPSG, EPSG, [lng, lat]);

return coord;
},

//将几何从大地坐标系转为平面坐标系37、38、39带
tranformToPlane: function (geo, fromEPSG) {
fromEPSG = fromEPSG || 'EPSG:4490';

var geometry;

if (!!geo.type && geo.type == 'Feature') {
  geometry = geo.geometry.coordinates;
} else if (!!geo.coordinates == true) {
  geometry = geo.coordinates;
} else if (Object.prototype.toString.call(geo) == '[object Array]') {
  geometry = geo;
}

if (geometry.length > 0 && Object.prototype.toString.call(geometry[0]) == '[object Number]') {
  var coord = geometric.tranformCoordsToPlane(geometry[0], geometry[1], fromEPSG);

  geometry[0] = coord[0];
  geometry[1] = coord[1];

  return geometry;
} else {
  for (var geo1 of geometry) {
    geometric.tranformToPlane(geo1);
  }

  return geometry;
}
},

//将坐标点从平面坐标系37、38、39转为大地坐标系
tranformCoordToGeodetic: function (lng, lat, toEPSG) {
toEPSG = toEPSG || 'EPSG:4490';

var EPSG;

if (lng < 38000000) {
  EPSG = 'EPSG:4525';
} else if (lng > 38000000 && lng < 39000000) {
  EPSG = 'EPSG:4526';
} else {
  EPSG = 'EPSG:4527';
}

var coord = proj4(EPSG, toEPSG, [lng, lat]);

return coord;
},

//从平面坐标系37、38、39带转为大地坐标系
tranformToGeodetic: function (geo, toEPSG) {
toEPSG = toEPSG || 'EPSG:4490';

var geometry;

if (!!geo.type && geo.type == 'Feature') {
  geometry = geo.geometry.coordinates;
} else if (!!geo.coordinates == true) {
  geometry = geo.coordinates;
} else if (Object.prototype.toString.call(geo) == '[object Array]') {
  geometry = geo;
}

if (geometry.length > 0 && Object.prototype.toString.call(geometry[0]) == '[object Number]') {
  var lng = geometry[0];
  var lat = geometry[1];

  var coord = geometric.tranformCoordToGeodetic(lng, lat, toEPSG);

  geometry[0] = coord[0];
  geometry[1] = coord[1];

  return geometry;
} else {
  for (var geo1 of geometry) {
    geometric.tranformToPlane(geo1);
  }

  return geometry;
}
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享